Skip to content
Closed
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
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ module github.com/LumeraProtocol/supernode
go 1.24.0

require (

github.com/LumeraProtocol/dd-service/gen v0.0.0-20250305185425-22977769a449
github.com/LumeraProtocol/lumera v0.4.3
github.com/LumeraProtocol/rq-service/gen v0.0.0-20250305185258-cf252902b897

cosmossdk.io/api v0.7.6
github.com/LumeraProtocol/lumera v0.4.2
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cenkalti/backoff/v4 v4.3.0
github.com/cosmos/btcutil v1.0.5
Expand Down Expand Up @@ -33,6 +37,7 @@ require (
)

require (
cosmossdk.io/api v0.7.6 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core v0.11.1 // indirect
cosmossdk.io/depinject v1.1.0 // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/LumeraProtocol/lumera v0.4.2 h1:yW7mwoYiBCcFLFNs9AgmaLc0DVkir95NGFtR2j/VYsw=
github.com/LumeraProtocol/lumera v0.4.2/go.mod h1:MRqVY+f8edEBkDvpr4z2nJpglp3Qj1OUvjeWvrvIUSM=
github.com/LumeraProtocol/dd-service/gen v0.0.0-20250305185425-22977769a449 h1:VwXwh/bNCNmj8OgIyM+LfqMCqqSGjRtQv983HiYCKcE=
github.com/LumeraProtocol/dd-service/gen v0.0.0-20250305185425-22977769a449/go.mod h1:/ieXOhfSDyTbcyB1GFmKr4t2b0YGYn0O8ikMNBMnOMA=
github.com/LumeraProtocol/lumera v0.4.3 h1:q/FuT+JOLIpYdlunczRUr6K85r9Sn0lKvGltSrj4r6s=
github.com/LumeraProtocol/lumera v0.4.3/go.mod h1:MRqVY+f8edEBkDvpr4z2nJpglp3Qj1OUvjeWvrvIUSM=
github.com/LumeraProtocol/rq-service/gen v0.0.0-20250305185258-cf252902b897 h1:sxqhMpcQm8KjDFvhs6yg3Vyv9gt9uxBnfpZRewxAFos=
github.com/LumeraProtocol/rq-service/gen v0.0.0-20250305185258-cf252902b897/go.mod h1:+b6pn5XADYaATzzaKRZtCeIyYW2845v34gZ8NaPtPgI=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
Expand Down
82 changes: 53 additions & 29 deletions p2p/kademlia/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/LumeraProtocol/supernode/pkg/errors"

"github.com/LumeraProtocol/supernode/pkg/log"
"github.com/LumeraProtocol/supernode/pkg/lumera"
ltc "github.com/LumeraProtocol/supernode/pkg/net/credentials"
)

Expand Down Expand Up @@ -77,7 +76,7 @@ func (s *DHT) setBootstrapNodesFromConfigVar(ctx context.Context, bootstrapNodes
}

nodes = append(nodes, &Node{
ID: []byte(lumeraAddress.Identity),
ID: []byte(lumeraAddress.Identity),
IP: lumeraAddress.Host,
Port: lumeraAddress.Port,
})
Expand All @@ -88,6 +87,7 @@ func (s *DHT) setBootstrapNodesFromConfigVar(ctx context.Context, bootstrapNodes
return nil
}

// ConfigureBootstrapNodes connects with lumera client & gets p2p boostrap ip & port
// ConfigureBootstrapNodes connects with lumera client & gets p2p boostrap ip & port
func (s *DHT) ConfigureBootstrapNodes(ctx context.Context, bootstrapNodes string) error {
if bootstrapNodes != "" {
Expand All @@ -100,53 +100,77 @@ func (s *DHT) ConfigureBootstrapNodes(ctx context.Context, bootstrapNodes string
}
selfAddress = fmt.Sprintf("%s:%d", selfAddress, s.options.Port)

get := func(ctx context.Context, f func(context.Context) (lumera.SuperNodeAddressInfos, error)) ([]*Node, error) {
mns, err := f(ctx)
var boostrapNodes []*Node

if s.options.LumeraClient != nil {
// Get the latest block to determine height
latestBlockResp, err := s.options.LumeraClient.Node().GetLatestBlock(ctx)
if err != nil {
return fmt.Errorf("failed to get latest block: %w", err)
}

// Get the block height
blockHeight := uint64(latestBlockResp.SdkBlock.Header.Height)

// Get top supernodes for this block
supernodeResp, err := s.options.LumeraClient.SuperNode().GetTopSuperNodesForBlock(ctx, blockHeight)
if err != nil {
return []*Node{}, err
return fmt.Errorf("failed to get top supernodes: %w", err)
}

mapNodes := map[string]*Node{}
for _, mn := range mns {
node, err := s.parseNode(mn.ExtP2P, selfAddress)

for _, supernode := range supernodeResp.Supernodes {
// Find the latest IP address (with highest block height)
var latestIP string
var maxHeight int64 = -1

for _, ipHistory := range supernode.PrevIpAddresses {
if ipHistory.Height > maxHeight {
maxHeight = ipHistory.Height
latestIP = ipHistory.Address
}
}

if latestIP == "" {
log.P2P().WithContext(ctx).
WithField("supernode", supernode.SupernodeAccount).
Warn("No valid IP address found for supernode")
continue
}

// Parse the node from the IP address
node, err := s.parseNode(latestIP, selfAddress)
if err != nil {
log.P2P().WithContext(ctx).WithError(err).WithField("extP2P", mn.ExtP2P).Warn("Skip Bad Boostrap Address")
log.P2P().WithContext(ctx).WithError(err).
WithField("address", latestIP).
WithField("supernode", supernode.SupernodeAccount).
Warn("Skip Bad Bootstrap Address")
continue
}

mapNodes[mn.ExtP2P] = node
// Store the supernode account as the node ID
node.ID = []byte(supernode.SupernodeAccount)
mapNodes[latestIP] = node
}

nodes := []*Node{}
// Convert the map to a slice
for _, node := range mapNodes {
nodes = append(nodes, node)
boostrapNodes = append(boostrapNodes, node)
}

return nodes, nil
}

var boostrapNodes []*Node
if s.options.LumeraNetwork != nil {
boostrapNodes, err := get(ctx, s.options.LumeraNetwork.MasterNodesExtra)
if err != nil {
return fmt.Errorf("masternodesTop failed: %s", err)
} else if len(boostrapNodes) == 0 {
boostrapNodes, err = get(ctx, s.options.LumeraNetwork.MasterNodesTop)
if err != nil {
return fmt.Errorf("masternodesExtra failed: %s", err)
} else if len(boostrapNodes) == 0 {
log.P2P().WithContext(ctx).Error("unable to fetch bootstrap ip. Missing extP2P")

return nil
}
}
if len(boostrapNodes) == 0 {
log.P2P().WithContext(ctx).Error("unable to fetch bootstrap IP addresses. No valid supernodes found.")
return nil
}

for _, node := range boostrapNodes {
log.P2P().WithContext(ctx).WithFields(log.Fields{
"bootstap_ip": node.IP,
"bootstrap_port": node.Port,
}).Info("adding p2p bootstap node")
"node_id": string(node.ID),
}).Info("adding p2p bootstrap node")
}

s.options.BootstrapNodes = append(s.options.BootstrapNodes, boostrapNodes...)
Expand Down
48 changes: 27 additions & 21 deletions p2p/kademlia/dht.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,34 @@ import (

"github.com/btcsuite/btcutil/base58"
"github.com/cenkalti/backoff/v4"
"github.com/cosmos/cosmos-sdk/crypto/keyring"

"github.com/LumeraProtocol/lumera/x/lumeraid/securekeyx"
"github.com/LumeraProtocol/supernode/pkg/errors"
"github.com/LumeraProtocol/supernode/pkg/log"
"github.com/LumeraProtocol/supernode/pkg/lumera"
ltc "github.com/LumeraProtocol/supernode/pkg/net/credentials"
"github.com/LumeraProtocol/supernode/pkg/storage"
"github.com/LumeraProtocol/supernode/pkg/storage/memory"
"github.com/LumeraProtocol/supernode/pkg/storage/rqstore"
"github.com/LumeraProtocol/supernode/pkg/utils"
"github.com/LumeraProtocol/supernode/pkg/lumera"
)

const (
defaultNetworkPort uint16 = 4445
defaultNetworkAddr = "0.0.0.0"
defaultRefreshTime = time.Second * 3600
defaultPingTime = time.Second * 10
defaultCleanupInterval = time.Minute * 2
defaultDisabledKeyExpirationInterval = time.Minute * 30
defaultRedundantDataCleanupInterval = 12 * time.Hour
defaultDeleteDataInterval = 11 * time.Hour
delKeysCountThreshold = 10
lowSpaceThreshold = 50 // GB
batchStoreSize = 2500
storeSameSymbolsBatchConcurrency = 1
storeSymbolsBatchConcurrency = 2.0
minimumDataStoreSuccessRate = 75.0
defaultNetworkPort uint16 = 4445
defaultNetworkAddr = "0.0.0.0"
defaultRefreshTime = time.Second * 3600
defaultPingTime = time.Second * 10
defaultCleanupInterval = time.Minute * 2
defaultDisabledKeyExpirationInterval = time.Minute * 30
defaultRedundantDataCleanupInterval = 12 * time.Hour
defaultDeleteDataInterval = 11 * time.Hour
delKeysCountThreshold = 10
lowSpaceThreshold = 50 // GB
batchStoreSize = 2500
storeSameSymbolsBatchConcurrency = 1
storeSymbolsBatchConcurrency = 2.0
minimumDataStoreSuccessRate = 75.0

maxIterations = 4
)
Expand Down Expand Up @@ -74,13 +75,16 @@ type Options struct {
// node there is no way to connect to the network
BootstrapNodes []*Node

LumeraClient *lumera.Client
// Lumera client for interacting with the blockchain
LumeraClient lumera.Client

LumeraNetwork *lumera.LumeraNetwork
// Keyring for credentials
Keyring keyring.Keyring

ExternalIP string
}

// NewDHT returns a new DHT node
// NewDHT returns a new DHT node
func NewDHT(ctx context.Context, store Store, metaStore MetaStore, options *Options, rqstore rqstore.Store) (*DHT, error) {
// validate the options, if it's invalid, set them to default value
Expand All @@ -107,13 +111,15 @@ func NewDHT(ctx context.Context, store Store, metaStore MetaStore, options *Opti
s.externalIP = options.ExternalIP
}

kr := options.LumeraClient.GetKeyring()
if kr == nil {
return nil, fmt.Errorf("keyring is not initialized in lumera client context")
// Check that keyring is provided
if options.Keyring == nil {
return nil, fmt.Errorf("keyring is required but not provided")
}

// Initialize client credentials with the provided keyring
clientCreds, err := ltc.NewClientCreds(&ltc.ClientOptions{
CommonOptions: ltc.CommonOptions{
Keyring: kr,
Keyring: options.Keyring,
LocalIdentity: string(options.ID),
PeerType: securekeyx.Supernode,
},
Expand Down
17 changes: 10 additions & 7 deletions p2p/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import (
"fmt"
"time"

"github.com/LumeraProtocol/supernode/p2p/kademlia"
"github.com/LumeraProtocol/supernode/p2p/kademlia/store/cloud.go"
"github.com/LumeraProtocol/supernode/p2p/kademlia/store/meta"

"github.com/LumeraProtocol/supernode/p2p/kademlia/store/sqlite"
"github.com/LumeraProtocol/supernode/pkg/errors"
"github.com/LumeraProtocol/supernode/pkg/log"
"github.com/LumeraProtocol/supernode/pkg/lumera"
"github.com/LumeraProtocol/supernode/pkg/storage/rqstore"
"github.com/LumeraProtocol/supernode/pkg/utils"
"github.com/LumeraProtocol/supernode/p2p/kademlia"
"github.com/LumeraProtocol/supernode/p2p/kademlia/store/sqlite"
"github.com/LumeraProtocol/supernode/pkg/lumera"
"github.com/btcsuite/btcutil/base58"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
)

const (
Expand Down Expand Up @@ -45,7 +45,8 @@ type p2p struct {
dht *kademlia.DHT // the kademlia network
config *Config // the service configuration
running bool // if the kademlia network is ready
lumeraClient *lumera.Client
lumeraClient lumera.Client
keyring keyring.Keyring // Add the keyring field
rqstore rqstore.Store
}

Expand Down Expand Up @@ -231,7 +232,8 @@ func (s *p2p) NClosestNodesWithIncludingNodeList(ctx context.Context, n int, key
func (s *p2p) configure(ctx context.Context) error {
// new the queries storage
kadOpts := &kademlia.Options{
LumeraClient: s.lumeraClient,
LumeraClient: s.lumeraClient,
Keyring: s.keyring, // Pass the keyring
BootstrapNodes: []*kademlia.Node{},
IP: s.config.ListenAddress,
Port: s.config.Port,
Expand Down Expand Up @@ -259,7 +261,7 @@ func (s *p2p) configure(ctx context.Context) error {
}

// New returns a new p2p instance.
func New(ctx context.Context, config *Config, lumeraClient *lumera.Client, rqstore rqstore.Store, cloud cloud.Storage, mst *sqlite.MigrationMetaStore) (P2P, error) {
func New(ctx context.Context, config *Config, lumeraClient lumera.Client, kr keyring.Keyring, rqstore rqstore.Store, cloud cloud.Storage, mst *sqlite.MigrationMetaStore) (P2P, error) {
store, err := sqlite.NewStore(ctx, config.DataDir, cloud, mst)
if err != nil {
return nil, errors.Errorf("new kademlia store: %w", err)
Expand All @@ -275,6 +277,7 @@ func New(ctx context.Context, config *Config, lumeraClient *lumera.Client, rqsto
metaStore: meta,
config: config,
lumeraClient: lumeraClient,
keyring: kr, // Store the keyring
rqstore: rqstore,
}, nil
}
Expand Down
23 changes: 12 additions & 11 deletions pkg/lumera/modules/action/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ func (m *module) GetAction(ctx context.Context, actionID string) (*types.QueryGe
return resp, nil
}

//// GetActionFee calculates fee for processing data with given size
//func (m *module) GetActionFee(ctx context.Context, dataSize string) (*types.QueryGetActionFeeResponse, error) {
// resp, err := m.client.GetActionFee(ctx, &types.QueryGetActionFeeRequest{
// DataSize: dataSize,
// })
// if err != nil {
// return nil, fmt.Errorf("failed to get action fee: %w", err)
// }
//
// return resp, nil
//}

// GetActionFee calculates fee for processing data with given size
func (m *module) GetActionFee(ctx context.Context, dataSize string) (*types.QueryGetActionFeeResponse, error) {
resp, err := m.client.GetActionFee(ctx, &types.QueryGetActionFeeRequest{
DataSize: dataSize,
})
if err != nil {
return nil, fmt.Errorf("failed to get action fee: %w", err)
}

return resp, nil
}
4 changes: 3 additions & 1 deletion pkg/lumera/modules/action/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
// Module defines the interface for interacting with the action module
type Module interface {
GetAction(ctx context.Context, actionID string) (*types.QueryGetActionResponse, error)
//GetActionFee(ctx context.Context, dataSize string) (*types.QueryGetActionFeeResponse, error)

GetActionFee(ctx context.Context, dataSize string) (*types.QueryGetActionFeeResponse, error)

}

// NewModule creates a new Action module client
Expand Down
Loading