Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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 go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ require (
gopkg.in/yaml.v2 v2.4.0
)

require google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect
require google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect

require (
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a h1:GIqLhp/cYUkuGuiT+vJk8vhOP86L4+SP5j8yXgeVpvI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
Expand Down
2 changes: 1 addition & 1 deletion mino/minows/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (a address) String() string {
}

// ConnectionType implements mino.Address
// Not used by minows
// Not used by Minows
func (a address) ConnectionType() mino.AddressConnectionType {
return mino.ACTws
}
Expand Down
24 changes: 14 additions & 10 deletions mino/minows/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package minows

import (
"fmt"

ma "github.com/multiformats/go-multiaddr"
"go.dedis.ch/dela/cli"
"go.dedis.ch/dela/cli/node"
"go.dedis.ch/dela/core/store/kv"
"go.dedis.ch/dela/mino"
"go.dedis.ch/dela/mino/minows/key"
"golang.org/x/xerrors"
)

Expand All @@ -22,6 +22,7 @@ func NewController() node.Initializer {

const flagListen = "listen"
const flagPublic = "public"
const flagInstance = "instance"

func (c controller) SetCommands(builder node.Builder) {
builder.SetStartFlags(
Expand All @@ -39,6 +40,12 @@ func (c controller) SetCommands(builder node.Builder) {
Required: false,
Value: "",
},
cli.IntFlag{
Name: flagInstance,
Usage: "Set the instance number (default 0)",
Required: false,
Value: 0,
},
)

cmd := builder.SetCommand("list")
Expand All @@ -58,11 +65,6 @@ func (c controller) OnStart(flags cli.Flags, inj node.Injector) error {
if err != nil {
return xerrors.Errorf("could not resolve db: %v", err)
}
storage := key.NewStorage(db)
key, err := storage.LoadOrCreate()
if err != nil {
return xerrors.Errorf("could not load key: %v", err)
}

var public ma.Multiaddr
p := flags.String(flagPublic)
Expand All @@ -73,7 +75,9 @@ func (c controller) OnStart(flags cli.Flags, inj node.Injector) error {
}
}

m, err := NewMinows(listen, public, key)
i := flags.Int(flagInstance)

m, err := NewMinows(listen, public, db, i)
if err != nil {
return xerrors.Errorf("could not start mino: %v", err)
}
Expand All @@ -82,14 +86,14 @@ func (c controller) OnStart(flags cli.Flags, inj node.Injector) error {
}

func (c controller) OnStop(inj node.Injector) error {
var m *minows
var m *Minows
err := inj.Resolve(&m)
if err != nil {
return xerrors.Errorf("could not resolve mino: %v", err)
}
err = m.stop()
err = m.Stop()
if err != nil {
return xerrors.Errorf("could not stop mino: %v", err)
return xerrors.Errorf("could not Stop mino: %v", err)
}
return nil
}
Expand Down
13 changes: 8 additions & 5 deletions mino/minows/controller_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package minows

import (
"testing"
"time"

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.dedis.ch/dela/cli"
"go.dedis.ch/dela/cli/node"
"go.dedis.ch/dela/testing/fake"
"testing"
"time"
)

func TestController_OnStart(t *testing.T) {
Expand All @@ -17,7 +18,7 @@ func TestController_OnStart(t *testing.T) {

err := ctrl.OnStart(flags, inj)
require.NoError(t, err)
var m *minows
var m *Minows
err = inj.Resolve(&m)
require.NoError(t, err)
}
Expand All @@ -28,7 +29,7 @@ func TestController_OptionalPublic(t *testing.T) {

err := ctrl.OnStart(flags, inj)
require.NoError(t, err)
var m *minows
var m *Minows
err = inj.Resolve(&m)
require.NoError(t, err)
}
Expand Down Expand Up @@ -78,10 +79,12 @@ func mustCreateController(t *testing.T, inj node.Injector) (node.Initializer, fu
}

func setUp(t *testing.T, listen string, public string) (
cli.Flags, node.Injector, node.Initializer, func()) {
cli.Flags, node.Injector, node.Initializer, func(),
) {
flags := new(mockFlags)
flags.On("String", "listen").Return(listen)
flags.On("String", "public").Return(public)
flags.On("Int", "instance").Return(0)
inj := node.NewInjector()
inj.Inject(fake.NewInMemoryDB())

Expand Down
4 changes: 2 additions & 2 deletions mino/minows/key/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func NewStorage(db kv.DB) *Storage {

// LoadOrCreate loads the private key from Storage or
// creates a new one if none exists.
func (s *Storage) LoadOrCreate() (crypto.PrivKey, error) {
key := []byte("private_key")
func (s *Storage) LoadOrCreate(index string) (crypto.PrivKey, error) {
key := []byte("private_key:" + index)
var buffer []byte
err := s.db.Update(func(tx kv.WritableTx) error {
bucket, err := tx.GetBucketOrCreate(s.bucket)
Expand Down
61 changes: 47 additions & 14 deletions mino/minows/mod.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package minows

import (
"regexp"
"strconv"
"strings"

"github.com/libp2p/go-libp2p/core/peer"
"github.com/rs/zerolog"
"go.dedis.ch/dela"
"go.dedis.ch/dela/core/store/kv"
"go.dedis.ch/dela/mino/minows/key"
"go.dedis.ch/dela/serde/json"
"regexp"
"strings"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
Expand All @@ -21,14 +26,17 @@ var pattern = regexp.MustCompile("^[a-zA-Z0-9]+$")

// Minows
// - implements mino.Mino
type minows struct {
type Minows struct {
logger zerolog.Logger

myAddr address
host host.Host
segments []string
rpcs map[string]any
factory addressFactory

privkey crypto.PrivKey
db kv.DB
}

// NewMinows creates a new Minows instance that starts listening.
Expand All @@ -39,9 +47,19 @@ type minows struct {
// `public` can be nil and will be determined
// by the listening address and the port the host has bound to.
// key: private key representing this mino instance's identity
func NewMinows(listen, public ma.Multiaddr, key crypto.PrivKey) (mino.Mino,
error) {
h, err := libp2p.New(libp2p.ListenAddrs(listen), libp2p.Identity(key))
func NewMinows(listen, public ma.Multiaddr, db kv.DB, instance int) (
mino.Mino,
error,
) {
// Load or generate a unique private key for the mino instance.
storage := key.NewStorage(db)

privk, err := storage.LoadOrCreate(strconv.Itoa(instance))
if err != nil {
return nil, xerrors.Errorf("could not load or generate key: %v", err)
}

h, err := libp2p.New(libp2p.ListenAddrs(listen), libp2p.Identity(privk))
if err != nil {
return nil, xerrors.Errorf("could not start host: %v", err)
}
Expand All @@ -54,40 +72,44 @@ func NewMinows(listen, public ma.Multiaddr, key crypto.PrivKey) (mino.Mino,
return nil, xerrors.Errorf("could not create address: %v", err)
}

return &minows{
return &Minows{
logger: dela.Logger.With().Str("mino", myAddr.String()).Logger(),
myAddr: myAddr,
segments: nil,
host: h,
rpcs: make(map[string]any),
factory: addressFactory{},
privkey: privk,
db: db,
}, nil
}

func (m *minows) GetAddressFactory() mino.AddressFactory {
func (m *Minows) GetAddressFactory() mino.AddressFactory {
return m.factory
}

func (m *minows) GetAddress() mino.Address {
func (m *Minows) GetAddress() mino.Address {
return m.myAddr
}

func (m *minows) WithSegment(segment string) mino.Mino {
func (m *Minows) WithSegment(segment string) mino.Mino {
if segment == "" {
return m
}

return &minows{
return &Minows{
logger: m.logger,
myAddr: m.myAddr,
segments: append(m.segments, segment),
host: m.host,
rpcs: make(map[string]any),
factory: addressFactory{},
privkey: m.privkey,
db: m.db,
}
}

func (m *minows) CreateRPC(name string, h mino.Handler, f serde.Factory) (mino.RPC, error) {
func (m *Minows) CreateRPC(name string, h mino.Handler, f serde.Factory) (mino.RPC, error) {
if len(m.rpcs) == 0 {
for _, seg := range m.segments {
if !pattern.MatchString(seg) {
Expand Down Expand Up @@ -122,6 +144,17 @@ func (m *minows) CreateRPC(name string, h mino.Handler, f serde.Factory) (mino.R
return r, nil
}

func (m *minows) stop() error {
return m.host.Close()
func (m *Minows) Stop() error {
err := m.host.Close()
if err != nil {
return err
}
err = m.db.Close()
return err
}

func (m *Minows) GetPeerID() string {
pid, _ := peer.IDFromPrivateKey(m.privkey)
s := pid.String()
return s
}
Loading
Loading