Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:
docker run \
--workdir /go/src/github.com/keep-network/keep-core \
go-build-env \
gotestsum -- -timeout 15m
gotestsum -- -timeout 15m ./...

- name: Build Docker Runtime Image
if: github.event_name != 'workflow_dispatch'
Expand Down
4 changes: 3 additions & 1 deletion cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,13 @@ func initBitcoinElectrumFlags(cmd *cobra.Command, cfg *config.Config) {

// Initialize flags for Network configuration.
func initNetworkFlags(cmd *cobra.Command, cfg *config.Config) {
// TODO: Remove in v3.0.0 along with isBootstrap() in start.go and
// the LibP2P.Bootstrap config field.
cmd.Flags().BoolVar(
&cfg.LibP2P.Bootstrap,
"network.bootstrap",
false,
"Run the client in bootstrap mode.",
"[DEPRECATED: remove in v3.0] Run the client in bootstrap mode. This flag is deprecated and will be removed in v3.0.",
)

cmd.Flags().StringSliceVar(
Expand Down
17 changes: 5 additions & 12 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ func start(cmd *cobra.Command) error {
}

func isBootstrap() bool {
if clientConfig.LibP2P.Bootstrap {
logger.Warnf("--network.bootstrap is deprecated and will be removed in a future release")
}
return clientConfig.LibP2P.Bootstrap
}

Expand All @@ -197,19 +200,9 @@ func initializeNetwork(
operatorPrivateKey *operator.PrivateKey,
blockCounter chain.BlockCounter,
) (net.Provider, error) {
bootstrapPeersPublicKeys, err := libp2p.ExtractPeersPublicKeys(
clientConfig.LibP2P.Peers,
)
if err != nil {
return nil, fmt.Errorf(
"error extracting bootstrap peers public keys: [%v]",
err,
)
}

firewall := firewall.AnyApplicationPolicy(
applications,
firewall.NewAllowList(bootstrapPeersPublicKeys),
firewall.EmptyAllowList(),
)

netProvider, err := libp2p.Connect(
Expand Down Expand Up @@ -244,7 +237,7 @@ func initializeClientInfo(
config.ClientInfo.NetworkMetricsTick,
)

registry.ObserveConnectedBootstrapCount(
registry.ObserveConnectedWellknownPeersCount(
netProvider,
config.LibP2P.Peers,
config.ClientInfo.NetworkMetricsTick,
Expand Down
59 changes: 59 additions & 0 deletions cmd/start_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"strings"
"testing"

"github.com/keep-network/keep-core/config"
"github.com/spf13/cobra"
)

func TestNetworkBootstrapFlagDescription_ContainsDeprecationNotice(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
cfg := &config.Config{}

initNetworkFlags(cmd, cfg)

flag := cmd.Flags().Lookup("network.bootstrap")
if flag == nil {
t.Fatal("expected network.bootstrap flag to be registered")
}

usageLower := strings.ToLower(flag.Usage)
if !strings.Contains(usageLower, "deprecated") {
t.Errorf(
"expected flag description to contain deprecation notice, got: %q",
flag.Usage,
)
}
}

func TestIsBootstrap(t *testing.T) {
tests := map[string]struct {
bootstrapValue bool
expected bool
}{
"returns true when bootstrap flag is set": {
bootstrapValue: true,
expected: true,
},
"returns false when bootstrap flag is not set": {
bootstrapValue: false,
expected: false,
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
originalBootstrap := clientConfig.LibP2P.Bootstrap
defer func() { clientConfig.LibP2P.Bootstrap = originalBootstrap }()

clientConfig.LibP2P.Bootstrap = tc.bootstrapValue

got := isBootstrap()
if got != tc.expected {
t.Errorf("expected isBootstrap() to return %v, got %v", tc.expected, got)
}
})
}
}
6 changes: 4 additions & 2 deletions config/_peers/mainnet
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/dns4/bst-a01.tbtc.boar.network/tcp/5001/ipfs/16Uiu2HAmAmCrLuUmnBgpavU8y8JBUN6jWAQ93JwydZy3ABRyY6wU
/dns4/bst-b01.tbtc.boar.network/tcp/5001/ipfs/16Uiu2HAm4w5HdJQxBnadGRepaiGfWVvtMzhdAGZVcrf9i71mv69V
# TODO: Add at least one additional mainnet peer across a different
# operator/ASN before production rollout. A single peer is a SPOF for
# initial peer discovery of fresh nodes.
/ip4/143.198.18.229/tcp/3919/ipfs/16Uiu2HAmDP4Z6LCogRMictJ6deGs4DRo99A5JTz5u3CLMg7URxC6
3 changes: 2 additions & 1 deletion config/_peers/testnet
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/dns4/bst-a01.test.keep.boar.network/tcp/6001/ipfs/16Uiu2HAmSLDSahiKyTbCNNu8wJmZAsiKF7wuYJ8mogY8ZuAG1jhu
/dns4/keep-operator-1.test.keep-nodes.io/tcp/3920/ipfs/16Uiu2HAmDrk2Bh4VNPUJfKRHTE2CvH9xfKzN4KFnmRJbGLkJFDqL
/dns4/keep-operator-2.test.keep-nodes.io/tcp/3920/ipfs/16Uiu2HAm3ex8rGzwFpWYbRreRUiX9JEYCKxp7KDMzB8RZ6fQWnMa
6 changes: 3 additions & 3 deletions config/peers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ func TestResolvePeers(t *testing.T) {
"mainnet network": {
network: network.Mainnet,
expectedPeers: []string{
"/dns4/bst-a01.tbtc.boar.network/tcp/5001/ipfs/16Uiu2HAmAmCrLuUmnBgpavU8y8JBUN6jWAQ93JwydZy3ABRyY6wU",
"/dns4/bst-b01.tbtc.boar.network/tcp/5001/ipfs/16Uiu2HAm4w5HdJQxBnadGRepaiGfWVvtMzhdAGZVcrf9i71mv69V",
"/ip4/143.198.18.229/tcp/3919/ipfs/16Uiu2HAmDP4Z6LCogRMictJ6deGs4DRo99A5JTz5u3CLMg7URxC6",
}},
"sepolia network": {
network: network.Testnet,
expectedPeers: []string{
"/dns4/bst-a01.test.keep.boar.network/tcp/6001/ipfs/16Uiu2HAmSLDSahiKyTbCNNu8wJmZAsiKF7wuYJ8mogY8ZuAG1jhu",
"/dns4/keep-operator-1.test.keep-nodes.io/tcp/3920/ipfs/16Uiu2HAmDrk2Bh4VNPUJfKRHTE2CvH9xfKzN4KFnmRJbGLkJFDqL",
"/dns4/keep-operator-2.test.keep-nodes.io/tcp/3920/ipfs/16Uiu2HAm3ex8rGzwFpWYbRreRUiX9JEYCKxp7KDMzB8RZ6fQWnMa",
},
},
"developer network": {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.24

toolchain go1.24.1


replace (
github.com/bnb-chain/tss-lib => github.com/threshold-network/tss-lib v0.0.0-20230901144531-2e712689cfbe
// btcd in version v.0.23 extracted `btcd/btcec` to a separate package `btcd/btcec/v2`.
Expand Down
26 changes: 15 additions & 11 deletions pkg/clientinfo/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ import (
type Source func() float64

// Names under which metrics are exposed.
//
// NOTE: ConnectedWellknownPeersCountMetricName was renamed from
// "connected_bootstrap_count" in v2.6.0. Update any Prometheus queries or
// Grafana dashboards that reference the old name.
const (
ConnectedPeersCountMetricName = "connected_peers_count"
ConnectedBootstrapCountMetricName = "connected_bootstrap_count"
EthConnectivityMetricName = "eth_connectivity"
BtcConnectivityMetricName = "btc_connectivity"
ClientInfoMetricName = "client_info"
ConnectedPeersCountMetricName = "connected_peers_count"
ConnectedWellknownPeersCountMetricName = "connected_wellknown_peers_count"
EthConnectivityMetricName = "eth_connectivity"
BtcConnectivityMetricName = "btc_connectivity"
ClientInfoMetricName = "client_info"
)

const (
Expand Down Expand Up @@ -55,17 +59,17 @@ func (r *Registry) ObserveConnectedPeersCount(
)
}

// ObserveConnectedBootstrapCount triggers an observation process of the
// connected_bootstrap_count metric.
func (r *Registry) ObserveConnectedBootstrapCount(
// ObserveConnectedWellknownPeersCount triggers an observation process of the
// connected_wellknown_peers_count metric.
func (r *Registry) ObserveConnectedWellknownPeersCount(
netProvider net.Provider,
bootstraps []string,
wellknownPeers []string,
tick time.Duration,
) {
input := func() float64 {
currentCount := 0

for _, address := range bootstraps {
for _, address := range wellknownPeers {
if netProvider.ConnectionManager().IsConnected(address) {
currentCount++
}
Expand All @@ -75,7 +79,7 @@ func (r *Registry) ObserveConnectedBootstrapCount(
}

r.observe(
ConnectedBootstrapCountMetricName,
ConnectedWellknownPeersCountMetricName,
input,
validateTick(tick, DefaultNetworkMetricsTick),
)
Expand Down
91 changes: 91 additions & 0 deletions pkg/clientinfo/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package clientinfo

import (
"context"
"testing"
"time"

keepclientinfo "github.com/keep-network/keep-common/pkg/clientinfo"
"github.com/keep-network/keep-core/pkg/net"
"github.com/keep-network/keep-core/pkg/operator"
)

// mockTransportIdentifier implements net.TransportIdentifier for testing.
type mockTransportIdentifier struct{}

func (m *mockTransportIdentifier) String() string { return "mock-id" }

// mockConnectionManager implements net.ConnectionManager for testing.
type mockConnectionManager struct {
connectedAddresses map[string]bool
}

func (m *mockConnectionManager) ConnectedPeers() []string { return nil }
func (m *mockConnectionManager) ConnectedPeersAddrInfo() map[string][]string {
return nil
}
func (m *mockConnectionManager) GetPeerPublicKey(string) (*operator.PublicKey, error) {
return nil, nil
}
func (m *mockConnectionManager) DisconnectPeer(string) {}
func (m *mockConnectionManager) AddrStrings() []string { return nil }
func (m *mockConnectionManager) IsConnected(address string) bool {
if m.connectedAddresses == nil {
return false
}
return m.connectedAddresses[address]
}

// mockProvider implements net.Provider for testing.
type mockProvider struct {
connectionManager net.ConnectionManager
}

func (m *mockProvider) ID() net.TransportIdentifier { return &mockTransportIdentifier{} }
func (m *mockProvider) Type() string { return "mock" }
func (m *mockProvider) BroadcastChannelFor(string) (net.BroadcastChannel, error) {
return nil, nil
}
func (m *mockProvider) ConnectionManager() net.ConnectionManager {
return m.connectionManager
}
func (m *mockProvider) CreateTransportIdentifier(
*operator.PublicKey,
) (net.TransportIdentifier, error) {
return nil, nil
}
func (m *mockProvider) BroadcastChannelForwarderFor(string) {}

// TestObserveConnectedWellknownPeersCount_Callable verifies that the renamed
// function exists on the Registry type and can be called without panicking.
func TestObserveConnectedWellknownPeersCount_Callable(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

registry := &Registry{keepclientinfo.NewRegistry(), ctx}

provider := &mockProvider{
connectionManager: &mockConnectionManager{
connectedAddresses: map[string]bool{
"/ip4/127.0.0.1/tcp/3919": true,
},
},
}

// The function should execute without panic. We use a recovered call
// to detect if the method does not exist or panics.
defer func() {
if r := recover(); r != nil {
t.Fatalf(
"ObserveConnectedWellknownPeersCount panicked: %v",
r,
)
}
}()

registry.ObserveConnectedWellknownPeersCount(
provider,
[]string{"/ip4/127.0.0.1/tcp/3919"},
1*time.Minute,
)
}
12 changes: 10 additions & 2 deletions pkg/firewall/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ func (al *AllowList) Contains(operatorPublicKey *operator.PublicKey) bool {
return al.allowedPublicKeys[operatorPublicKey.String()]
}

// EmptyAllowList represents an empty firewall allowlist.
var EmptyAllowList = NewAllowList([]*operator.PublicKey{})
// emptyAllowList is the singleton empty allowlist used in production.
// All peers must pass IsRecognized checks; no bypass is available.
var emptyAllowList = NewAllowList([]*operator.PublicKey{})

// EmptyAllowList returns the empty firewall allowlist. In production, this
// ensures all peers are subject to on-chain staking verification with no
// AllowList bypass.
func EmptyAllowList() *AllowList {
return emptyAllowList
}

const (
// PositiveIsRecognizedCachePeriod is the time period the cache maintains
Expand Down
Loading
Loading