Skip to content

Commit

Permalink
Merge branch 'development' into haiko/remove-ecs-gha
Browse files Browse the repository at this point in the history
  • Loading branch information
haikoschol authored Feb 3, 2025
2 parents 72723bf + 5437f22 commit 35e885d
Show file tree
Hide file tree
Showing 43 changed files with 1,171 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
- name: Generate coverage report
run: |
go test ./... -coverprofile=coverage.out -covermode=atomic -timeout=20m
- uses: codecov/codecov-action@v5.1.2
- uses: codecov/codecov-action@v5.3.1
with:
files: ./coverage.out
flags: unit-tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:
- name: Test - Race
run: make test-using-race-detector

- uses: codecov/codecov-action@v5.1.2
- uses: codecov/codecov-action@v5.3.1
with:
if_ci_failed: success
informational: true
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
>
> The Gossamer Polkadot Host is pre-production software [2022-12-01]
>Developed by [ChainSafe](https://chainsafe.io) and funded by a Web3 Foundation grant and Polkadot [Treasury proposals](https://polkadot.polkassembly.io/treasury/808?tab=description).
>
Gossamer is a [Golang](https://go.dev/) implementation of the
[Polkadot Host](https://wiki.polkadot.network/docs/learn-polkadot-host): an
execution environment for the Polkadot runtime, which is materialized as a Web
Expand All @@ -43,6 +46,7 @@ Polkadot Host must orchestrate a number of interrelated services, such as
[networking](dot/network/README.md), block production, block finalization, a
JSON-RPC server, [and more](cmd/gossamer/README.md#client-components).


## Getting Started

To get started with Gossamer, follow the steps below to build the source code
Expand Down
1 change: 1 addition & 0 deletions chain/kusama/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func DefaultConfig() *cfg.Config {
config.Core.GrandpaAuthority = false
config.Core.Role = 1
config.Network.NoMDNS = false
config.Core.Sync = "full"

return config
}
1 change: 1 addition & 0 deletions chain/paseo/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func DefaultConfig() *cfg.Config {
config.Core.GrandpaAuthority = false
config.Core.Role = 1
config.Network.NoMDNS = false
config.Core.Sync = "full"

return config
}
1 change: 1 addition & 0 deletions chain/polkadot/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func DefaultConfig() *cfg.Config {
config.Core.GrandpaAuthority = false
config.Core.Role = 1
config.Network.NoMDNS = false
config.Core.Sync = "full"

return config
}
1 change: 1 addition & 0 deletions chain/westend-dev/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func DefaultConfig() *cfg.Config {
config.RPC.UnsafeRPC = true
config.RPC.WSExternal = true
config.RPC.UnsafeWSExternal = true
config.Core.Sync = "full"

return config
}
1 change: 1 addition & 0 deletions chain/westend-local/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func DefaultConfig() *cfg.Config {
config.RPC.UnsafeRPC = true
config.RPC.WSExternal = true
config.RPC.UnsafeWSExternal = true
config.Core.Sync = "full"

return config
}
Expand Down
1 change: 1 addition & 0 deletions chain/westend/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func DefaultConfig() *cfg.Config {
config.Core.GrandpaAuthority = false
config.Core.Role = 1
config.Network.NoMDNS = false
config.Core.Sync = "full"

return config
}
8 changes: 8 additions & 0 deletions cmd/gossamer/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,14 @@ func addCoreFlags(cmd *cobra.Command) error {
return fmt.Errorf("failed to add --grandpa-interval flag: %s", err)
}

if err := addStringFlagBindViper(cmd,
"sync",
config.Core.Sync,
"sync mode [warp | full]",
"core.sync"); err != nil {
return fmt.Errorf("failed to add --sync flag: %s", err)
}

return nil
}

Expand Down
7 changes: 7 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ const (
DefaultSystemName = "Gossamer"
// DefaultSystemVersion is the default system version
DefaultSystemVersion = "0.0.0"

// DefaultSyncMode is the default block sync mode
DefaultSyncMode = "full"
)

// DefaultRPCModules the default RPC modules
Expand Down Expand Up @@ -188,6 +191,7 @@ type CoreConfig struct {
GrandpaAuthority bool `mapstructure:"grandpa-authority"`
WasmInterpreter string `mapstructure:"wasm-interpreter,omitempty"`
GrandpaInterval time.Duration `mapstructure:"grandpa-interval,omitempty"`
Sync string `mapstructure:"sync,omitempty"`
}

// StateConfig contains the configuration for the state.
Expand Down Expand Up @@ -363,6 +367,7 @@ func DefaultConfig() *Config {
GrandpaAuthority: true,
WasmInterpreter: DefaultWasmInterpreter,
GrandpaInterval: DefaultDiscoveryInterval,
Sync: DefaultSyncMode,
},
Network: &NetworkConfig{
Port: DefaultNetworkPort,
Expand Down Expand Up @@ -444,6 +449,7 @@ func DefaultConfigFromSpec(nodeSpec *genesis.Genesis) *Config {
GrandpaAuthority: true,
WasmInterpreter: DefaultWasmInterpreter,
GrandpaInterval: DefaultDiscoveryInterval,
Sync: DefaultSyncMode,
},
Network: &NetworkConfig{
Port: DefaultNetworkPort,
Expand Down Expand Up @@ -525,6 +531,7 @@ func Copy(c *Config) Config {
GrandpaAuthority: c.Core.GrandpaAuthority,
WasmInterpreter: c.Core.WasmInterpreter,
GrandpaInterval: c.Core.GrandpaInterval,
Sync: c.Core.Sync,
},
Network: &NetworkConfig{
Port: c.Network.Port,
Expand Down
39 changes: 39 additions & 0 deletions docs/docs/design/authority-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
layout: default
title: Authority Discovery Overview
permalink: /design/authority-discovery/
---

# Authority Discovery

## Questions

### Is the authority discovery implemented on Kademlia for a custom peer discovery?

No, it uses Kademlia capabilities however it adds a custom handlers for DHT Events, like: DhtEvent::ValueFound
- DhtEvent::ValueNotFound
- DhtEvent::ValuePut
- DhtEvent::ValuePutFailed
- DhtEvent::PutRecordRequest

These events are produced by the Discovery layer (Kademlia) and propagated to the `authority-discovery` that handles each of them. Specifically for `DhtEvent::PutRecordRequest` it does a validation step and then store the record.

What happens is that the `authority-discovery` is the actual protocol implementation for discovery in substrate/polkadot given that it produces and store the records that are available in the DHT for other peers to query, validate and use.

### What are the functionalities of the authority discovery, beyond discovery new peers based on its authority ids?

- Publish the node external address, more specifically, create the authority discovery record, sign it and distributing through DHT allowing other nodes to query it.
- Handle DHT events, validating incoming records and caching other authorities address.

### What subsystems uses the authority discovery mechanism? Describe the usages.

- Availability Distribution
- Availability Recovery
- Gossip Support

### Check if we can currently extend the authority discovery protocol can to golang kademlia p2p library

Yes, we pretty much can implement the protocol.
- We are able to encode the records using the same [proto schema used by substrate/polkadot](https://github.com/paritytech/polkadot-sdk/blob/master/substrate/client/authority-discovery/src/worker/schema/dht-v3.proto) - We can query for specific keys in DHT.
- What can write a custom validator to validate incoming records.
- golang-libp2p does not works in the same way rust-libp2p works by enabling us to receive those DHT events but we can achieve the same protocol implementation using what the library provide to us.
36 changes: 36 additions & 0 deletions docs/docs/design/gossip-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
layout: default
title: Gossip Support
permalink: /design/gossip-support/
---

# Gossip Support

Gossip support is a short subsystem that cares about handling active leaves and network bridge update events.

## Functionalities

- **Check connectivity**: The subsystem contains a timer that triggers every 600 seconds (10 minutes) a connectivity check that is a simple verification on the amount of authorities connected against the actual set of authorities, if the percentage of connected authorities is bellow 90% the node will issue WARN logs.

- **Handle Active Leaves**:
- Given the current values in the state, **last failure** and **last connection request**, the subsystem should force new requests or re-resolve authorities
- Determine if the current session index has changed, if so determine relevant validators and issue connection request. The subsystem should change the **last sesison index** value only if it is possible to retrieve the new session info.
- If we notice that a new session is starting we should update our authority ids cache and send a `NetworkBridgeRxMessage::UpdatedAuthorityIds` message with informations about the new set of authorities.

- **Handle Network Bridge Update**:
- In the above point, when handling active leaves, we issue connection requests and whenever a new connection is stablished or a disconnection happens for some reason. The subsytems listen on any network bridge update about `NetworkBridgeEvent::PeerConnected` and `NetworkBridgeEvent::PeerDisconnected`, other updates are not important.

## State

The subsystem state is composed of:

- Keystore
- Last Session Index
- **Last Failure**: last time we could not resolve a third of the authorities
- **Last Connection Request**: is possible that validators change their peer IDs in during a session. If that happens we will reconnect to them in the best case after a session, so we need to try more often to resolve peers and reconnect to them. We cannot detect changes faster them Authority Discovery DHT queries.
- **Failure Start**: first time the node cannot reach the connectivity threshold
- **Resolved Authorities**: A map of resolved authority IDs to a set of multiaddr, basically we were able to find the addresses for authorities, not mean we are actually connected to them.
- **Connected Authorities**: A map of actual authorities ID's connected to their PeerId
- **Connected Peers**: A map of PeerId to authority IDs for fast lookup
- **Authority Discovery**: authority discovery service, allows us to resolve authorities addresses.

6 changes: 6 additions & 0 deletions docs/docs/design/statement-distribution.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
---
layout: default
title: Statement Distribution
permalink: /design/statement-distribution/
---

# Statement Distribution

This subsystem is responsible for distributing signed statements that we have generated and forwarding statements generated by our peers.
Expand Down
4 changes: 4 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ nav:
- Availability Subsystems: ./design/availability-subsystems.md
- Prospective Parachains: ./design/prospective-parachains.md
- Prospective Parachains - Fragment Chain: ./design/fragment-chain.md
- Authority Discovery: ./design/authority-discovery.md
- Statement Distribution: ./design/statement-distribution.md
- Grid Topology: ./design/grid-topology.md
- Gossip Support: ./design/gossip-support.md
- Contributing:
- Overview: ./contributing.md
extra_css:
Expand Down
12 changes: 11 additions & 1 deletion dot/network/host_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package network

import (
"fmt"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -396,12 +397,21 @@ func Test_PeerSupportsProtocol(t *testing.T) {
}
require.NoError(t, err)

genesisHash := nodeA.blockState.GenesisHash().String()
genesisHash = strings.TrimPrefix(genesisHash, "0x")
fullSyncProtocolId := fmt.Sprintf("/%s%s", genesisHash, SyncID)
warpSyncProtocolId := fmt.Sprintf("/%s%s", genesisHash, WarpSyncID)

tests := []struct {
protocol protocol.ID
expect bool
}{
{
protocol: protocol.ID("/gossamer/test/0/sync/2"),
protocol: protocol.ID(fullSyncProtocolId),
expect: true,
},
{
protocol: protocol.ID(warpSyncProtocolId),
expect: true,
},
{
Expand Down
6 changes: 6 additions & 0 deletions dot/network/messages/warp_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type WarpProofRequest struct {
Begin common.Hash
}

func NewWarpProofRequest(from common.Hash) *WarpProofRequest {
return &WarpProofRequest{
Begin: from,
}
}

// Decode decodes the message into a WarpProofRequest
func (wpr *WarpProofRequest) Decode(in []byte) error {
return scale.Unmarshal(in, wpr)
Expand Down
5 changes: 3 additions & 2 deletions dot/network/mock_warp_sync_provider_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions dot/network/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,14 @@ func (s *Service) Start() error {
s.ctx, s.cancel = context.WithCancel(context.Background())
}

genesisHashProtocolId := protocol.ID(s.cfg.BlockState.GenesisHash().String())
genesisHash := s.blockState.GenesisHash().String()
genesisHash = strings.TrimPrefix(genesisHash, "0x")
fullSyncProtocolId := fmt.Sprintf("/%s%s", genesisHash, SyncID)
warpSyncProtocolId := fmt.Sprintf("/%s%s", genesisHash, WarpSyncID)

s.host.registerStreamHandler(s.host.protocolID+SyncID, s.handleSyncStream)
s.host.registerStreamHandler(protocol.ID(fullSyncProtocolId), s.handleSyncStream)
s.host.registerStreamHandler(s.host.protocolID+lightID, s.handleLightStream)
s.host.registerStreamHandler(genesisHashProtocolId+WarpSyncID, s.handleWarpSyncStream)
s.host.registerStreamHandler(protocol.ID(warpSyncProtocolId), s.handleWarpSyncStream)

// register block announce protocol
err := s.RegisterNotificationsProtocol(
Expand Down Expand Up @@ -622,13 +625,16 @@ func (s *Service) SendMessage(to peer.ID, msg NotificationsMessage) error {
func (s *Service) GetRequestResponseProtocol(subprotocol string, requestTimeout time.Duration,
maxResponseSize uint64) *RequestResponseProtocol {

protocolID := s.host.protocolID + protocol.ID(subprotocol)
genesisHash := s.blockState.GenesisHash().String()
genesisHash = strings.TrimPrefix(genesisHash, "0x")
protocolId := fmt.Sprintf("/%s%s", genesisHash, subprotocol)

return &RequestResponseProtocol{
ctx: s.ctx,
host: s.host,
requestTimeout: requestTimeout,
maxResponseSize: maxResponseSize,
protocolID: protocolID,
protocolID: protocol.ID(protocolId),
responseBuf: make([]byte, maxResponseSize),
responseBufMu: sync.Mutex{},
}
Expand Down
11 changes: 2 additions & 9 deletions dot/network/warp_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,16 @@ import (
"fmt"

"github.com/ChainSafe/gossamer/dot/network/messages"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/primitives/consensus/grandpa"
primitives "github.com/ChainSafe/gossamer/internal/primitives/consensus/grandpa"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/grandpa/warpsync"
libp2pnetwork "github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
)

const MaxAllowedSameRequestPerPeer = 5

type WarpSyncVerificationResult struct {
SetId grandpa.SetID
AuthorityList primitives.AuthorityList
Header types.Header
Completed bool
}

// WarpSyncProvider is an interface for generating warp sync proofs
type WarpSyncProvider interface {
// Generate proof starting at given block hash. The proof is accumulated until maximum proof
Expand All @@ -34,7 +27,7 @@ type WarpSyncProvider interface {
encodedProof []byte,
setId grandpa.SetID,
authorities primitives.AuthorityList,
) (*WarpSyncVerificationResult, error)
) (*warpsync.WarpSyncVerificationResult, error)
}

func (s *Service) handleWarpSyncRequest(req messages.WarpProofRequest) ([]byte, error) {
Expand Down
10 changes: 10 additions & 0 deletions dot/peerset/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,14 @@ const (
// SameBlockSyncRequest used when a peer send us more than the max number of the same request.
SameBlockSyncRequest Reputation = math.MinInt32
SameBlockSyncRequestReason = "same block sync request"

// UnexpectedResponseValue is used when peer send an unexpected response.
UnexpectedResponseValue Reputation = -(1 << 29)
// UnexpectedResponseReason is used when peer send an unexpected response.
UnexpectedResponseReason = "Unexpected response"

// BadWarpProofValue is used when peer send invalid warp sync proof.
BadWarpProofValue Reputation = -(1 << 29)
// BadWarpProofReason is used when peer send invalid warp sync proof.
BadWarpProofReason = "Bad warp proof"
)
Loading

0 comments on commit 35e885d

Please sign in to comment.