Skip to content

Commit

Permalink
WIP site config
Browse files Browse the repository at this point in the history
  • Loading branch information
burdiyan committed Sep 13, 2023
1 parent a9699d7 commit 396f0c0
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 104 deletions.
97 changes: 52 additions & 45 deletions backend/cmd/mintter-site/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,95 +6,102 @@ import (
"errors"
"flag"
"fmt"
"net/url"
"os"

"mintter/backend/config"
"mintter/backend/core"
"mintter/backend/daemon"
accounts "mintter/backend/genproto/accounts/v1alpha"
protodaemon "mintter/backend/genproto/daemon/v1alpha"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/burdiyan/go/mainutil"
"github.com/peterbourgon/ff/v3"
)

func main() {
const envVarPrefix = "MINTTER_SITE"
const envVarPrefix = "MINTTER"

mainutil.Run(func() error {
ctx := mainutil.TrapSignals()

fs := flag.NewFlagSet("mintter-site", flag.ExitOnError)
fs.Usage = func() {
fmt.Fprintf(fs.Output(), `Usage: %s ADDRESS [flags]
cfg := config.Default()
cfg.P2P.NoListing = true
This program is similar to our main mintterd program in a lot of ways, but has more suitable defaults for running on a server as site.
// We parse flags twice here, once without the config file setting, and then with it.
// This is because we want the config file to be in the repo path, which can be changed
// with flags or env vars. We don't allow setting a config file explicitly, but the repo path
// can change. We need to know the requested repo path in the first place, and then figure out the config file.
It requires one positional argument ADDRESS, which has to be a Web network address this site is supposed to be available at.
The address can be a DNS name, or an IP address, and it has to be a URL with a scheme and port (if applicable).
Examples:
- http://127.0.0.1:42542
- https://mintter.com
- http://example.com
if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarPrefix(envVarPrefix)); err != nil {
return err
Flags:
`, fs.Name())
fs.PrintDefaults()
}

if err := cfg.Base.ExpandDataDir(); err != nil {
return err
// TODO(burdiyan): ignore http.port flag because it collides with the ADDRESS positional argument.
cfg := config.Default()
cfg.DataDir = "~/.mintter-site"
cfg.BindFlags(fs)

if len(os.Args) < 2 {
fs.Usage()
fmt.Fprintln(fs.Output(), "Error: Positional argument ADDRESS is missing.")
os.Exit(2)
}

cfgFile, err := config.EnsureConfigFile(cfg.DataDir)
rawURL := os.Args[1]
u, err := url.Parse(rawURL)
if err != nil {
return err
return fmt.Errorf("failed to parse address: %w", err)
}

if err := ff.Parse(fs, os.Args[1:],
ff.WithEnvVarPrefix(envVarPrefix),
ff.WithConfigFileParser(ff.PlainParser),
ff.WithConfigFile(cfgFile),
ff.WithAllowMissingConfigFile(false),
); err != nil {
return err
if u.Path != "" {
return fmt.Errorf("address URL must not have a path: %s", rawURL)
}

app, err := daemon.Load(ctx, cfg)
if err != nil {
return err
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("address URL only supports http or https, got = %s", rawURL)
}

const mnemonicWords = 12
mnemonic, err := core.NewBIP39Mnemonic(mnemonicWords)
if err != nil {
if err := ff.Parse(fs, os.Args[2:], ff.WithEnvVarPrefix(envVarPrefix)); err != nil {
return err
}

_, err = app.RPC.Daemon.Register(ctx, &protodaemon.RegisterRequest{
Mnemonic: mnemonic,
Passphrase: "",
})
stat, ok := status.FromError(err)
if !ok && stat.Code() != codes.AlreadyExists {
if err := cfg.Base.ExpandDataDir(); err != nil {
return err
}

_, err = app.Storage.Identity().Await(ctx)
dir, err := daemon.InitRepo(cfg.Base.DataDir, nil)
if err != nil {
return err
}
const alias = "Web gateway"
const bio = "Find me at https://www.mintter.com"
acc, err := app.RPC.Accounts.UpdateProfile(ctx, &accounts.Profile{
Alias: alias,
Bio: bio,
})

app, err := daemon.LoadWithStorage(ctx, cfg, dir)
if err != nil {
return err
}
if acc.Profile.Alias != alias || acc.Profile.Bio != bio {
return fmt.Errorf("unexpected alias/bio. %s", acc.Profile.Alias+". "+acc.Profile.Bio)

if _, ok := dir.Identity().Get(); !ok {
account, err := core.NewKeyPairRandom()
if err != nil {
return fmt.Errorf("failed to generate random account key pair: %w", err)
}

if err := app.RPC.Daemon.RegisterAccount(ctx, account); err != nil {
return fmt.Errorf("failed to create registration: %w", err)
}
}

if _, err := app.RPC.Accounts.UpdateProfile(ctx, &accounts.Profile{
Alias: rawURL + " Hypermedia Site",
}); err != nil {
return fmt.Errorf("failed to update profile: %w", err)
}

err = app.Wait()
if errors.Is(err, context.Canceled) {
return nil
Expand Down
4 changes: 2 additions & 2 deletions backend/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ type P2P struct {
func (p2p *P2P) BindFlags(fs *flag.FlagSet) {
fs.IntVar(&p2p.Port, "p2p.port", p2p.Port, "Port to listen for incoming P2P connections")
fs.BoolVar(&p2p.NoRelay, "p2p.no-relay", p2p.NoRelay, "Disable libp2p circuit relay")
fs.Var(newAddrsFlag(p2p.BootstrapPeers, &p2p.BootstrapPeers), "p2p.bootstrap-peers", "Addresses for bootstrap nodes (comma separated)")
fs.Var(newAddrsFlag(p2p.AnnounceAddrs, &p2p.AnnounceAddrs), "p2p.announce-addrs", "Addresses will be announced for this node to be reachable at (comma separated multiaddresses format). overrides no-private-ips")
fs.Var(newAddrsFlag(p2p.BootstrapPeers, &p2p.BootstrapPeers), "p2p.bootstrap-peers", "Multiaddrs for bootstrap nodes (comma separated)")
fs.Var(newAddrsFlag(p2p.AnnounceAddrs, &p2p.AnnounceAddrs), "p2p.announce-addrs", "Multiaddrs this node will announce as being reachable at (comma separated). When set, -p2p.no-private-ips flag is ignored.")
fs.BoolVar(&p2p.PublicReachability, "p2p.public-reachability", p2p.PublicReachability, "Force Reachability to public.")
fs.Var(newAddrsFlag(p2p.ListenAddrs, &p2p.ListenAddrs), "p2p.listen-addrs", "Addresses to be listen at (comma separated multiaddresses format)")
fs.BoolVar(&p2p.NoPrivateIps, "p2p.no-private-ips", p2p.NoPrivateIps, "Not announce local IPs.")
Expand Down
4 changes: 2 additions & 2 deletions backend/core/coretest/coretest.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewTester(name string) Tester {
panic(err)
}

dev, err := core.NewKeyPair(core.CodecDeviceKey, dpriv.(*crypto.Ed25519PrivateKey))
dev, err := core.NewKeyPair(dpriv.(*crypto.Ed25519PrivateKey))
if err != nil {
panic(err)
}
Expand All @@ -63,7 +63,7 @@ func NewTester(name string) Tester {
panic(err)
}

acc, err := core.NewKeyPair(core.CodecAccountKey, apriv.(*crypto.Ed25519PrivateKey))
acc, err := core.NewKeyPair(apriv.(*crypto.Ed25519PrivateKey))
if err != nil {
panic(err)
}
Expand Down
3 changes: 1 addition & 2 deletions backend/core/coretest/coretest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ func TestKeys(t *testing.T) {
require.NoError(t, err)

require.True(t, alice.Device.ID() == pid)
require.True(t, alice.Device.CID().Equals(peer.ToCid(pid)))
}

func TestEncoding(t *testing.T) {
Expand All @@ -24,7 +23,7 @@ func TestEncoding(t *testing.T) {
data, err := alice.Account.MarshalBinary()
require.NoError(t, err)

pk, err := core.ParsePublicKey(core.CodecAccountKey, data)
pk, err := core.ParsePublicKey(data)
require.NoError(t, err)
require.Equal(t, alice.Account.String(), pk.String())
}
45 changes: 10 additions & 35 deletions backend/core/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ import (
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multihash"
)

// Multicodecs.
const (
CodecDeviceKey = cid.Libp2pKey
// TODO: need to register this codec withing the multicodecs repo table.
CodecAccountKey = 1091161161
)

// Ensure interface implementations.
Expand Down Expand Up @@ -72,15 +64,14 @@ type KeyID = peer.ID

// PublicKey is the public part of a KeyPair.
type PublicKey struct {
k crypto.PubKey
id KeyID
codec uint64
k crypto.PubKey
id KeyID

abbrev uint64
}

// NewPublicKey creates a new public key from an existing Ed25519 public key.
func NewPublicKey(codec uint64, pub crypto.PubKey) (pk PublicKey, err error) {
func NewPublicKey(pub crypto.PubKey) (pk PublicKey, err error) {
_, ok := pub.(*crypto.Ed25519PublicKey)
if !ok {
return pk, fmt.Errorf("only Ed25519 public keys are supported, but got %T", pub)
Expand All @@ -104,7 +95,6 @@ func NewPublicKey(codec uint64, pub crypto.PubKey) (pk PublicKey, err error) {
return PublicKey{
k: pub,
id: pid,
codec: codec,
abbrev: *(*uint64)(unsafe.Pointer(&b)),
}, nil
}
Expand All @@ -122,11 +112,11 @@ func PublicKeyFromCID(c cid.Cid) (pk PublicKey, err error) {
return pk, err
}

return NewPublicKey(c.Prefix().Codec, pub.(*crypto.Ed25519PublicKey))
return NewPublicKey(pub.(*crypto.Ed25519PublicKey))
}

// ParsePublicKey parses existing libp2p-encoded key material.
func ParsePublicKey(codec uint64, data []byte) (pk PublicKey, err error) {
func ParsePublicKey(data []byte) (pk PublicKey, err error) {
pub, err := crypto.UnmarshalPublicKey(data)
if err != nil {
return pk, err
Expand All @@ -136,7 +126,7 @@ func ParsePublicKey(codec uint64, data []byte) (pk PublicKey, err error) {
return pk, fmt.Errorf("only ed25519 keys are supported")
}

return NewPublicKey(codec, pub.(*crypto.Ed25519PublicKey))
return NewPublicKey(pub.(*crypto.Ed25519PublicKey))
}

// Abbrev returns the abbreviated form of the public key,
Expand All @@ -152,16 +142,6 @@ func (pk PublicKey) PeerID() peer.ID {
return pk.id
}

// CID returns CID representation of the public key.
func (pk PublicKey) CID() cid.Cid {
mh, err := multihash.Cast([]byte(pk.id))
if err != nil {
panic(err)
}

return cid.NewCidV1(pk.codec, mh)
}

// String creates string representation of the public key.
func (pk PublicKey) String() string {
return pk.Principal().String()
Expand All @@ -172,11 +152,6 @@ func (pk PublicKey) Principal() Principal {
return PrincipalFromPubKey(pk.k)
}

// Codec returns multicodec of the public key.
func (pk PublicKey) Codec() uint64 {
return pk.codec
}

// Verify implements Verifier.
func (pk PublicKey) Verify(data []byte, s Signature) error {
return s.verify(pk.k, data)
Expand Down Expand Up @@ -205,24 +180,24 @@ type KeyPair struct {
}

// NewKeyPairRandom creates a new random KeyPair with a given multicodec prefix.
func NewKeyPairRandom(codec uint64) (kp KeyPair, err error) {
func NewKeyPairRandom() (kp KeyPair, err error) {
priv, _, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
return kp, fmt.Errorf("failed to generate device private key: %w", err)
}

return NewKeyPair(codec, priv.(*crypto.Ed25519PrivateKey))
return NewKeyPair(priv.(*crypto.Ed25519PrivateKey))
}

// NewKeyPair creates a new KeyPair with a given multicodec prefix from an existing instance
// of the private key. At the moment only Ed25519 keys are supported.
func NewKeyPair(codec uint64, priv crypto.PrivKey) (kp KeyPair, err error) {
func NewKeyPair(priv crypto.PrivKey) (kp KeyPair, err error) {
_, ok := priv.(*crypto.Ed25519PrivateKey)
if !ok {
return kp, fmt.Errorf("only ed25519 keys are supported")
}

pub, err := NewPublicKey(codec, priv.GetPublic().(*crypto.Ed25519PublicKey))
pub, err := NewPublicKey(priv.GetPublic().(*crypto.Ed25519PublicKey))
if err != nil {
return kp, err
}
Expand Down
10 changes: 1 addition & 9 deletions backend/core/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@ type Identity struct {
}

func NewIdentity(account PublicKey, device KeyPair) Identity {
if account.Codec() != CodecAccountKey {
panic("not account key")
}

if device.Codec() != CodecDeviceKey {
panic("not device key")
}

return Identity{
account: account,
device: device,
Expand Down Expand Up @@ -69,7 +61,7 @@ func AccountFromSeed(rand []byte) (KeyPair, error) {
return KeyPair{}, err
}

return NewKeyPair(CodecAccountKey, priv.(*crypto.Ed25519PrivateKey))
return NewKeyPair(priv.(*crypto.Ed25519PrivateKey))
}

// NewBIP39Mnemonic creates a new random BIP-39 compatible mnemonic words.
Expand Down
6 changes: 3 additions & 3 deletions backend/daemon/storage/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (d *Dir) init() (currentVersion string, err error) {
}

if d.device.Wrapped() == nil {
kp, err := core.NewKeyPairRandom(core.CodecDeviceKey)
kp, err := core.NewKeyPairRandom()
if err != nil {
return "", fmt.Errorf("failed to generate random device key: %w", err)
}
Expand Down Expand Up @@ -212,7 +212,7 @@ func (d *Dir) maybeLoadAccountKey() error {
return err
}

account, err := core.NewPublicKey(core.CodecAccountKey, pub)
account, err := core.NewPublicKey(pub)
if err != nil {
return err
}
Expand Down Expand Up @@ -283,5 +283,5 @@ func loadDeviceKeyFromFile(dir string) (kp core.KeyPair, err error) {
return kp, fmt.Errorf("failed to unmarshal private key for device: %w", err)
}

return core.NewKeyPair(core.CodecDeviceKey, pk)
return core.NewKeyPair(pk)
}
2 changes: 1 addition & 1 deletion backend/daemon/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewWithDeviceKey(path string, log *zap.Logger, pk crypto.PrivKey) (*Dir, er
return nil, err
}

kp, err := core.NewKeyPair(core.CodecDeviceKey, pk)
kp, err := core.NewKeyPair(pk)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions backend/lndhub/lndhub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ func TestCreate(t *testing.T) {
defer cancel()
identity := future.New[core.Identity]()
lndHubClient := NewClient(context.Background(), &http.Client{}, pool, identity.ReadOnly, mintterDomain, lnaddressDomain)
keypair, err := core.NewKeyPairRandom(core.CodecDeviceKey)
keypair, err := core.NewKeyPairRandom()
require.NoError(t, err)
priv, pub, err := crypto.GenerateEd25519Key(nil)
require.NoError(t, err)
pubkeyBytes, err := pub.Raw()
require.NoError(t, err)

pubkey, err := core.NewPublicKey(core.CodecAccountKey, pub.(*crypto.Ed25519PublicKey))
pubkey, err := core.NewPublicKey(pub.(*crypto.Ed25519PublicKey))
require.NoError(t, err)

login := pubkey.CID().String()
login := pubkey.Principal().String()
passwordBytes, err := priv.Sign([]byte(SigninMessage))
password := hex.EncodeToString(passwordBytes)
require.NoError(t, err)
Expand Down
Loading

0 comments on commit 396f0c0

Please sign in to comment.