From 8c36e21aed2d2cf3c34271dc5c09c09021506047 Mon Sep 17 00:00:00 2001 From: Alexandr Burdiyan Date: Thu, 21 Sep 2023 18:33:36 +0200 Subject: [PATCH] feat(backend): almost finished site syncing --- backend/BUILD.plz | 1 - backend/cmd/mintter-site/sites/daemon.go | 27 +- backend/cmd/mintter-site/sites/sites.go | 214 +++++----- backend/cmd/mintter-site/sites/sites_test.go | 55 +++ backend/cmd/mintter-site/sitesql/BUILD.plz | 27 -- .../cmd/mintter-site/sitesql/queries.gen.go | 62 --- .../cmd/mintter-site/sitesql/queries.gensum | 2 - backend/cmd/mintter-site/sitesql/queries.go | 49 --- backend/cmd/mintter-site/sitesql/sitesql.go | 29 -- .../api/documents/v1alpha/documents_test.go | 3 - .../api/entities/v1alpha/entities_test.go | 1 - backend/daemon/api/groups/v1alpha/db.go | 25 +- backend/daemon/api/groups/v1alpha/groups.go | 17 +- backend/daemon/storage/migrations.go | 14 + backend/daemon/storage/schema.gensum | 2 +- backend/daemon/storage/schema.sql | 8 +- backend/daemon/storage/sqlite.go | 23 ++ backend/genproto/p2p/v1alpha/p2p.pb.go | 368 +++++++++--------- backend/hyper/hypersql/queries.manual.go | 3 +- backend/pkg/debugx/debugx.go | 27 ++ backend/pkg/dqb/dqb.go | 3 - backend/pkg/slicex/slicex.go | 15 + backend/pkg/sqlitedbg/sqlitedbg.go | 5 + proto/p2p/v1alpha/go.gensum | 4 +- 24 files changed, 497 insertions(+), 487 deletions(-) delete mode 100644 backend/cmd/mintter-site/sitesql/BUILD.plz delete mode 100644 backend/cmd/mintter-site/sitesql/queries.gen.go delete mode 100644 backend/cmd/mintter-site/sitesql/queries.gensum delete mode 100644 backend/cmd/mintter-site/sitesql/queries.go delete mode 100644 backend/cmd/mintter-site/sitesql/sitesql.go create mode 100644 backend/pkg/debugx/debugx.go diff --git a/backend/BUILD.plz b/backend/BUILD.plz index a6fe5ab9dd..3bcce3cc90 100644 --- a/backend/BUILD.plz +++ b/backend/BUILD.plz @@ -8,7 +8,6 @@ go_binary( ["**/*.go"], exclude = ["**/*_test.go"], ) + [ - "//backend/cmd/mintter-site/sitesql:go_library", "//backend/daemon/storage:go_library", "//backend/hyper/hypersql:go_library", "//backend/lndhub/lndhubsql:go_library", diff --git a/backend/cmd/mintter-site/sites/daemon.go b/backend/cmd/mintter-site/sites/daemon.go index f66e037312..7ea4395731 100644 --- a/backend/cmd/mintter-site/sites/daemon.go +++ b/backend/cmd/mintter-site/sites/daemon.go @@ -9,13 +9,15 @@ import ( "mintter/backend/daemon" "mintter/backend/daemon/storage" accounts "mintter/backend/genproto/accounts/v1alpha" + "mintter/backend/hyper" "mintter/backend/ipfs" "mintter/backend/mttnet" "mintter/backend/pkg/future" - "mintter/backend/pkg/must" + "mintter/backend/pkg/slicex" "net/url" "crawshaw.io/sqlite/sqlitex" + "github.com/multiformats/go-multiaddr" ) // App is the site daemon app. @@ -42,13 +44,16 @@ func Load(ctx context.Context, address string, cfg config.Config, dir *storage.D return nil, fmt.Errorf("address URL must not have a path: %s", address) } - cfg.P2P.AnnounceAddrs = must.Do2( - ipfs.ParseMultiaddrs( - ipfs.DefaultListenAddrsDNS(u.Hostname(), cfg.P2P.Port))) + cfg.P2P.AnnounceAddrs, err = slicex.MapE(ipfs.DefaultListenAddrsDNS(u.Hostname(), cfg.P2P.Port), multiaddr.NewMultiaddr) + if err != nil { + panic(fmt.Errorf("failed to parse announce addresses: %w", err)) + } + + nodePromise := future.New[*mttnet.Node]() + dbPromise := future.New[*sqlitex.Pool]() + blobsPromise := future.New[*hyper.Storage]() - nf := future.New[*mttnet.Node]() - ndb := future.New[*sqlitex.Pool]() - site := NewServer(address, nf.ReadOnly, ndb.ReadOnly) + site := NewServer(address, blobsPromise.ReadOnly, nodePromise.ReadOnly, dbPromise.ReadOnly) app, err := daemon.Load(ctx, cfg, dir, site, daemon.GenericHandler{ Path: "/.well-known/hypermedia-site", @@ -61,7 +66,7 @@ func Load(ctx context.Context, address string, cfg config.Config, dir *storage.D // This is some ugly stuff. Site server needs some stuff that are passed from the daemon. go func() { - if err := ndb.Resolve(app.DB); err != nil { + if err := dbPromise.Resolve(app.DB); err != nil { panic(err) } @@ -70,7 +75,11 @@ func Load(ctx context.Context, address string, cfg config.Config, dir *storage.D panic(err) } - if err := nf.Resolve(node); err != nil { + if err := nodePromise.Resolve(node); err != nil { + panic(err) + } + + if err := blobsPromise.Resolve(app.Blobs); err != nil { panic(err) } }() diff --git a/backend/cmd/mintter-site/sites/sites.go b/backend/cmd/mintter-site/sites/sites.go index 0793c36ce0..c575688b3a 100644 --- a/backend/cmd/mintter-site/sites/sites.go +++ b/backend/cmd/mintter-site/sites/sites.go @@ -7,13 +7,14 @@ import ( "encoding/base64" "errors" "fmt" - "mintter/backend/cmd/mintter-site/sitesql" + "mintter/backend/daemon/storage" groups "mintter/backend/genproto/groups/v1alpha" "mintter/backend/hyper" "mintter/backend/hyper/hypersql" "mintter/backend/mttnet" "mintter/backend/pkg/future" + "mintter/backend/pkg/slicex" "net/http" "sync" @@ -24,17 +25,16 @@ import ( "crawshaw.io/sqlite/sqlitex" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/peer" + "github.com/multiformats/go-multiaddr" "google.golang.org/protobuf/encoding/protojson" ) // Website is the gate to manipulate internal node structures type Website struct { - // Network of the node. - node *future.ReadOnly[*mttnet.Node] - // db access to the node. - db *future.ReadOnly[*sqlitex.Pool] - // url is the protocol + hostname the group is being served at. - url string + blobs *future.ReadOnly[*hyper.Storage] + node *future.ReadOnly[*mttnet.Node] + db *future.ReadOnly[*sqlitex.Pool] + url string once sync.Once setupSecret string @@ -43,19 +43,20 @@ type Website struct { var errNodeNotReadyYet = errors.New("P2P node is not ready yet") // NewServer creates a new server for the site. -func NewServer(url string, n *future.ReadOnly[*mttnet.Node], db *future.ReadOnly[*sqlitex.Pool]) *Website { +func NewServer(url string, blobs *future.ReadOnly[*hyper.Storage], n *future.ReadOnly[*mttnet.Node], db *future.ReadOnly[*sqlitex.Pool]) *Website { return &Website{ - node: n, - db: db, - url: url, + blobs: blobs, + node: n, + db: db, + url: url, } } -func (ws *Website) ServeHTTP(w http.ResponseWriter, _ *http.Request) { +func (ws *Website) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET") - siteInfo, err := ws.GetSiteInfo(context.Background(), &groups.GetSiteInfoRequest{}) + siteInfo, err := ws.GetSiteInfo(r.Context(), &groups.GetSiteInfoRequest{}) if err != nil { if errors.Is(err, errNodeNotReadyYet) { w.Header().Set("Retry-After", "30") @@ -107,6 +108,11 @@ func (ws *Website) getSetupSecret(ctx context.Context) string { return ws.setupSecret } +const ( + keySiteGroup = "site_group_id" + keySiteOwner = "site_owner_id" +) + // GetSiteInfo exposes the public information of a site. Which group is serving and how to reach the site via p2p. func (ws *Website) GetSiteInfo(ctx context.Context, in *groups.GetSiteInfoRequest) (*groups.PublicSiteInfo, error) { n, ok := ws.node.Get() @@ -121,42 +127,35 @@ func (ws *Website) GetSiteInfo(ctx context.Context, in *groups.GetSiteInfoReques conn, release, err := db.Conn(ctx) if err != nil { - return nil, fmt.Errorf("Failed to get db connection: %w", err) + return nil, err } defer release() - gid, err := sitesql.GetServedGroupID(conn) + groupID, err := storage.GetKV(conn, keySiteGroup) if err != nil { - return nil, fmt.Errorf("Failed to get group id from the db: %w", err) - } - - resp := &groups.PublicSiteInfo{ - PeerInfo: &groups.PeerInfo{}, - GroupId: gid.KVValue, + return nil, fmt.Errorf("failed to get group id from the db: %w", err) } - for _, address := range n.AddrInfo().Addrs { - resp.PeerInfo.Addrs = append(resp.PeerInfo.Addrs, address.String()) - } - resp.PeerInfo.PeerId = n.ID().DeviceKey().PeerID().String() - resp.PeerInfo.AccountId = n.ID().Account().ID().String() + ai := n.AddrInfo() - groupID, err := sitesql.GetServedGroupID(conn) - if err != nil { - return nil, fmt.Errorf("Could not get group ID: %w", err) - } - if groupID.KVValue == "" { - // The site is not initialized yet - return resp, nil + resp := &groups.PublicSiteInfo{ + PeerInfo: &groups.PeerInfo{ + PeerId: ai.ID.String(), + AccountId: n.ID().Account().ID().String(), + Addrs: slicex.Map(ai.Addrs, multiaddr.Multiaddr.String), + }, + GroupId: groupID, } - entity, err := n.Blobs().LoadEntity(ctx, hyper.EntityID(groupID.KVValue)) - if err != nil { - return nil, fmt.Errorf("could not get entity [%s]: %w", groupID.KVValue, err) - } + if groupID != "" { + entity, err := n.Blobs().LoadEntity(ctx, hyper.EntityID(groupID)) + if err != nil { + return nil, err + } - if entity != nil { - resp.GroupVersion = entity.Version().String() + if entity != nil { + resp.GroupVersion = entity.Version().String() + } } return resp, nil @@ -169,6 +168,10 @@ func (ws *Website) InitializeServer(ctx context.Context, in *groups.InitializeSe return nil, errNodeNotReadyYet } + if in.GroupId == "" { + return nil, status.Errorf(codes.InvalidArgument, "group ID is required") + } + gid, err := ws.GetGroupID(ctx) if err != nil { return nil, err @@ -187,7 +190,7 @@ func (ws *Website) InitializeServer(ctx context.Context, in *groups.InitializeSe return nil, fmt.Errorf("failed to extract peer ID from headers: %w", err) } - _, err = n.AccountForDevice(ctx, remoteDeviceID) + owner, err := n.AccountForDevice(ctx, remoteDeviceID) if err != nil { return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", remoteDeviceID.String(), err) } @@ -208,8 +211,12 @@ func (ws *Website) InitializeServer(ctx context.Context, in *groups.InitializeSe return nil, err } - if err := sitesql.SetServedGroupID(conn, in.GroupId); err != nil { - return nil, err + if err := storage.SetKV(conn, keySiteGroup, in.GroupId, false); err != nil { + return nil, fmt.Errorf("failed to save group ID") + } + + if err := storage.SetKV(conn, keySiteOwner, owner.String(), false); err != nil { + return nil, fmt.Errorf("failed to save owner") } return &groups.InitializeServerResponse{}, nil @@ -229,12 +236,12 @@ func (ws *Website) GetGroupID(ctx context.Context) (string, error) { } defer release() - dbgroup, err := sitesql.GetServedGroupID(conn) + groupID, err := storage.GetKV(conn, keySiteGroup) if err != nil { return "", err } - return dbgroup.KVValue, nil + return groupID, nil } // PublishBlobs publish blobs to the website. @@ -248,16 +255,6 @@ func (ws *Website) PublishBlobs(ctx context.Context, in *groups.PublishBlobsRequ return nil, errNodeNotReadyYet } - db, err := ws.db.Await(ctx) - if err != nil { - return nil, err - } - conn, release, err := db.Conn(ctx) - if err != nil { - return nil, fmt.Errorf("Failed to get db connection: %w", err) - } - defer release() - // Get caller identity info, ok := rpcpeer.FromContext(ctx) if !ok { @@ -269,70 +266,103 @@ func (ws *Website) PublishBlobs(ctx context.Context, in *groups.PublishBlobsRequ return nil, err } - authorAcc, err := n.AccountForDevice(ctx, pid) + callerAccount, err := n.AccountForDevice(ctx, pid) if err != nil { return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", pid.String(), err) } - // Get the owner's view of the list of members. - groupID, err := sitesql.GetServedGroupID(conn) - if err != nil || groupID.KVValue == "" { - return nil, fmt.Errorf("Error getting groupID on the site, is the site initialized?: %w", err) + db, err := ws.db.Await(ctx) + if err != nil { + return nil, err } - - edb, err := hypersql.LookupEnsure(conn, storage.LookupResource, groupID.KVValue) + conn, release, err := db.Conn(ctx) if err != nil { - return nil, fmt.Errorf("Could not get group (%s) resource: %w", groupID.KVValue, err) + return nil, fmt.Errorf("Failed to get db connection: %w", err) } + defer release() - groupOwner, err := hypersql.ResourceGetOwner(conn, edb) - if err != nil { - return nil, fmt.Errorf("Could not get the owner of the group %s: %w", groupID.KVValue, err) + // Get the owner's view of the list of members. + groupID, err := storage.GetKV(conn, keySiteGroup) + if err != nil || groupID == "" { + return nil, fmt.Errorf("error getting groupID on the site, is the site initialized?: %w", err) } - pkdb, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, authorAcc) - if err != nil { - return nil, fmt.Errorf("couldn't get member entity for account [%s]: %w", authorAcc.String(), err) + var role groups.Role + { + edb, err := hypersql.LookupEnsure(conn, storage.LookupResource, groupID) + if err != nil { + return nil, fmt.Errorf("couldn't get group (%s) resource: %w", groupID, err) + } + + owner, err := storage.GetKV(conn, keySiteOwner) + if err != nil || owner == "" { + return nil, fmt.Errorf("error getting owner on the site, is the site initialized?: %w", err) + } + + if owner == callerAccount.String() { + role = groups.Role_OWNER + } else { + groupOwner, err := hypersql.ResourceGetOwner(conn, edb) + if err != nil { + return nil, fmt.Errorf("couldn't get the owner of the group %s: %w", groupID, err) + } + + pkdb, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, callerAccount) + if err != nil { + return nil, fmt.Errorf("couldn't get member entity for account [%s]: %w", callerAccount.String(), err) + } + + // See if the caller is in the owner's group + r, err := hypersql.GroupGetRole(conn, edb, groupOwner, pkdb) + if err != nil { + return nil, fmt.Errorf("couldn't get role of member %s in group %s: %w", callerAccount.String(), groupID, err) + } + + role = groups.Role(r) + } } - // See if the caller is in the owner's group - role, err := hypersql.GroupGetRole(conn, edb, groupOwner, pkdb) - if err != nil { - return nil, fmt.Errorf("Could not get role of member %s in group %s: %w", authorAcc.String(), groupID.KVValue, err) + if role != groups.Role_OWNER && role != groups.Role_EDITOR { + return nil, status.Errorf(codes.PermissionDenied, "Caller [%s] does not have enough permissions to publish to this site.", callerAccount.String()) } - if role == int64(groups.Role_ROLE_UNSPECIFIED) { - return nil, status.Errorf(codes.PermissionDenied, "Caller [%s] does not have enough permissions to publish to this site.", authorAcc.String()) + blobs, err := ws.blobs.Await(ctx) + if err != nil { + return nil, err } - want := []cid.Cid{} - for _, cIDStr := range in.Blobs { - c, err := cid.Parse(cIDStr) + bs := blobs.IPFSBlockstore() + + var want []cid.Cid + for _, x := range in.Blobs { + c, err := cid.Parse(x) if err != nil { - return nil, fmt.Errorf("Could not parse provided blob [%s]: %w", cIDStr, err) + return nil, fmt.Errorf("failed to parse CID %s: %w", x, err) } - res, err := hypersql.BlobsHave(conn, c.Hash()) + + ok, err := bs.Has(ctx, c) if err != nil { - return nil, fmt.Errorf("Could not verify if we had blob [%s] or not: %w", c.String(), err) + return nil, fmt.Errorf("failed to check if we have blob %s: %w", c.String(), err) } - if res.Have == 0 { + if !ok { want = append(want, c) } } - ses := n.Bitswap().NewSession(ctx) - blkCh, err := ses.GetBlocks(ctx, want) - if err != nil { - return nil, fmt.Errorf("Could not get bitswap channel: %w", err) - } - for { - blk, ok := <-blkCh - if !ok { - return &groups.PublishBlobsResponse{}, nil + + sess := n.Bitswap().NewSession(ctx) + // We don't use sess.GetBlocks here because we care about the order of blobs for correct indexing. + for _, c := range want { + blk, err := sess.GetBlock(ctx, c) + if err != nil { + return nil, fmt.Errorf("could not get block %s: %w", c.String(), err) } - if err := n.Blobs().IPFSBlockstore().Put(ctx, blk); err != nil { - return nil, fmt.Errorf("Could not store block %s", blk.Cid().String()) + + if err := bs.Put(ctx, blk); err != nil { + return nil, fmt.Errorf("could not store block %s: %w", c.String(), err) } } + + return &groups.PublishBlobsResponse{}, nil } // getRemoteID gets the remote peer id if there is an opened p2p connection between them with context ctx. diff --git a/backend/cmd/mintter-site/sites/sites_test.go b/backend/cmd/mintter-site/sites/sites_test.go index d1795de458..ef7ce81a0c 100644 --- a/backend/cmd/mintter-site/sites/sites_test.go +++ b/backend/cmd/mintter-site/sites/sites_test.go @@ -6,6 +6,7 @@ import ( "mintter/backend/config" "mintter/backend/core/coretest" "mintter/backend/daemon" + accounts "mintter/backend/genproto/accounts/v1alpha" groups "mintter/backend/genproto/groups/v1alpha" "mintter/backend/ipfs" "mintter/backend/pkg/must" @@ -51,6 +52,60 @@ func TestSiteInit(t *testing.T) { require.Nil(t, init) require.Error(t, err, "subsequent init must fail") require.Equal(t, codes.FailedPrecondition, status.Code(err), "subsequent init must fail with precondition error") + + info, err := site.Website.GetSiteInfo(ctx, &groups.GetSiteInfoRequest{}) + require.NoError(t, err) + require.Equal(t, group.Id, info.GroupId, "site must serve the correct group ID") + require.Equal(t, "", info.GroupVersion, "version must be empty before publishing") +} + +func TestSiteSync(t *testing.T) { + t.Parallel() + + site := makeTestSite(t, "carol") + alice := daemon.MakeTestApp(t, "alice", daemon.MakeTestConfig(t), true) + bob := daemon.MakeTestApp(t, "bob", daemon.MakeTestConfig(t), true) + david := daemon.MakeTestApp(t, "david", daemon.MakeTestConfig(t), true) + ctx := context.Background() + + require.NoError(t, alice.Net.MustGet().Connect(ctx, bob.Net.MustGet().AddrInfo()), "alice must connect to bob") + + group, err := alice.RPC.Groups.CreateGroup(ctx, &groups.CreateGroupRequest{ + Title: "My test group", + }) + require.NoError(t, err) + + group, err = alice.RPC.Groups.UpdateGroup(ctx, &groups.UpdateGroupRequest{ + Id: group.Id, + UpdatedMembers: map[string]groups.Role{ + bob.Storage.Identity().MustGet().Account().Principal().String(): groups.Role_EDITOR, + }, + }) + require.NoError(t, err) + + group, err = alice.RPC.Groups.UpdateGroup(ctx, &groups.UpdateGroupRequest{ + Id: group.Id, + SiteSetupUrl: site.Website.GetSetupURL(ctx), + }) + require.NoError(t, err) + + err = alice.RPC.Groups.SyncSite(ctx, site.Address.String(), 0) + require.NoError(t, err, "alice must be able to sync with the site as an owner") + _ = david + + info, err := site.Website.GetSiteInfo(ctx, &groups.GetSiteInfoRequest{}) + require.NoError(t, err) + require.Equal(t, group.Id, info.GroupId, "site must serve the correct group ID") + require.NotEqual(t, "", info.GroupVersion, "version must be non-empty after publishing") + + return + // TODO(burdiyan): fix this test. + + bobOnSite, err := site.RPC.Accounts.GetAccount(ctx, &accounts.GetAccountRequest{ + Id: bob.Storage.Identity().MustGet().Account().Principal().String(), + }) + require.NoError(t, err, "site must get bob's account from the group") + require.NotEqual(t, "", bobOnSite.Profile.Alias, "site must have bob's account because he's a member of the group") } func makeTestSite(t *testing.T, name string) *App { diff --git a/backend/cmd/mintter-site/sitesql/BUILD.plz b/backend/cmd/mintter-site/sitesql/BUILD.plz deleted file mode 100644 index 60f0e4106e..0000000000 --- a/backend/cmd/mintter-site/sitesql/BUILD.plz +++ /dev/null @@ -1,27 +0,0 @@ -subinclude("//build/rules/go:defs", "//build/rules/codegen:defs") - -# Generates SQLite queries for the sites to use. -# This could be defined inside the package itself, -# but then the Go source files would need to be -# exposed and depended on in the `mintterd` rule. -generated( - name = "queries", - srcs = ["queries.go"], - outs = ["queries.gen.go"], - cmd = """ -export GOROOT="$($TOOLS_GO env GOROOT)" -export PATH="$PATH:${GOROOT%/share/go}/bin" -cd $PKG -$TOOLS_GORUN -tags codegen generateQueries -""", - tools = [ - "//build/nix:go", - "//build/tools:gorun", - ], -) - -filegroup( - name = "go_library", - srcs = glob(["*.go"]), - visibility = ["//backend/..."], -) diff --git a/backend/cmd/mintter-site/sitesql/queries.gen.go b/backend/cmd/mintter-site/sitesql/queries.gen.go deleted file mode 100644 index 025300446b..0000000000 --- a/backend/cmd/mintter-site/sitesql/queries.gen.go +++ /dev/null @@ -1,62 +0,0 @@ -// Code generated by sqlitegen. DO NOT EDIT. - -package sitesql - -import ( - "errors" - "fmt" - - "crawshaw.io/sqlite" - "mintter/backend/pkg/sqlitegen" -) - -var _ = errors.New - -func SetServedGroupID(conn *sqlite.Conn, link string) error { - const query = `INSERT OR REPLACE INTO kv (key, value) -VALUES ('site_group_id', :link)` - - before := func(stmt *sqlite.Stmt) { - stmt.SetText(":link", link) - } - - onStep := func(i int, stmt *sqlite.Stmt) error { - return nil - } - - err := sqlitegen.ExecStmt(conn, query, before, onStep) - if err != nil { - err = fmt.Errorf("failed query: SetServedGroupID: %w", err) - } - - return err -} - -type GetServedGroupIDResult struct { - KVValue string -} - -func GetServedGroupID(conn *sqlite.Conn) (GetServedGroupIDResult, error) { - const query = `SELECT kv.value FROM kv WHERE kv.key ='site_group_id'` - - var out GetServedGroupIDResult - - before := func(stmt *sqlite.Stmt) { - } - - onStep := func(i int, stmt *sqlite.Stmt) error { - if i > 1 { - return errors.New("GetServedGroupID: more than one result return for a single-kind query") - } - - out.KVValue = stmt.ColumnText(0) - return nil - } - - err := sqlitegen.ExecStmt(conn, query, before, onStep) - if err != nil { - err = fmt.Errorf("failed query: GetServedGroupID: %w", err) - } - - return out, err -} diff --git a/backend/cmd/mintter-site/sitesql/queries.gensum b/backend/cmd/mintter-site/sitesql/queries.gensum deleted file mode 100644 index 97e71c6456..0000000000 --- a/backend/cmd/mintter-site/sitesql/queries.gensum +++ /dev/null @@ -1,2 +0,0 @@ -srcs: aa43be8cc99dd78bbf728cee50b0b5eb -outs: 8758b18717cb7ac28ae1bb1759ead80e diff --git a/backend/cmd/mintter-site/sitesql/queries.go b/backend/cmd/mintter-site/sitesql/queries.go deleted file mode 100644 index c0b7392a9a..0000000000 --- a/backend/cmd/mintter-site/sitesql/queries.go +++ /dev/null @@ -1,49 +0,0 @@ -// Package sitesql implements all the database related functions. -package sitesql - -import ( - s "mintter/backend/daemon/storage" - "mintter/backend/pkg/sqlitegen" - "mintter/backend/pkg/sqlitegen/qb" - "os" -) - -var _ = generateQueries - -const ( - // SiteRegistrationLinkKey is the column name of the meta table where we store the registration link. - SiteRegistrationLinkKey = "site_registration_link" - // SiteGroupIDKey is the group ID this site is serving. This is populated once the site is remotely initialized with the secret link. - SiteGroupIDKey = "site_group_id" - // SiteGroupVersionKey is the specific versiont of the group this site is serving. This may change through the life of the site as editors update it. - SiteGroupVersionKey = "site_group_version" -) - -//go:generate gorun -tags codegen generateQueries -func generateQueries() error { - code, err := sqlitegen.CodegenQueries("sitesql", - qb.MakeQuery(s.Schema, "SetServedGroupID", sqlitegen.QueryKindExec, - "INSERT OR REPLACE INTO", s.KV, qb.ListColShort( - s.KVKey, - s.KVValue, - ), '\n', - "VALUES", qb.List( - "'"+SiteGroupIDKey+"'", - qb.Var("link", sqlitegen.TypeText), - ), - ), - - qb.MakeQuery(s.Schema, "GetServedGroupID", sqlitegen.QueryKindSingle, - "SELECT", qb.Results( - qb.ResultCol(s.KVValue), - ), - "FROM", s.KV, - "WHERE", s.KVKey, "='"+SiteGroupIDKey+"'", - ), - ) - if err != nil { - return err - } - - return os.WriteFile("queries.gen.go", code, 0600) -} diff --git a/backend/cmd/mintter-site/sitesql/sitesql.go b/backend/cmd/mintter-site/sitesql/sitesql.go deleted file mode 100644 index 25e26f91f1..0000000000 --- a/backend/cmd/mintter-site/sitesql/sitesql.go +++ /dev/null @@ -1,29 +0,0 @@ -package sitesql - -import ( - "mintter/backend/hyper/hypersql" - - "crawshaw.io/sqlite" -) - -func ensurePublicKey(conn *sqlite.Conn, key []byte) (int64, error) { - res, err := hypersql.PublicKeysLookupID(conn, key) - if err != nil { - return 0, err - } - - if res.PublicKeysID > 0 { - return res.PublicKeysID, nil - } - - ins, err := hypersql.PublicKeysInsert(conn, key) - if err != nil { - return 0, err - } - - if ins.PublicKeysID <= 0 { - panic("BUG: failed to insert key for some reason") - } - - return ins.PublicKeysID, nil -} diff --git a/backend/daemon/api/documents/v1alpha/documents_test.go b/backend/daemon/api/documents/v1alpha/documents_test.go index 09e55576a7..0f8f6cdf9b 100644 --- a/backend/daemon/api/documents/v1alpha/documents_test.go +++ b/backend/daemon/api/documents/v1alpha/documents_test.go @@ -16,13 +16,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/sanity-io/litter" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" ) -var _ = litter.Dump - func TestAPICreateDraft(t *testing.T) { t.Parallel() diff --git a/backend/daemon/api/entities/v1alpha/entities_test.go b/backend/daemon/api/entities/v1alpha/entities_test.go index c6a6146d2e..6436d78e2f 100644 --- a/backend/daemon/api/entities/v1alpha/entities_test.go +++ b/backend/daemon/api/entities/v1alpha/entities_test.go @@ -33,7 +33,6 @@ type onceFunc struct { func (o *onceFunc) Do() string { o.once.Do(func() { - fmt.Println("doing") o.val = o.fn() }) return o.val diff --git a/backend/daemon/api/groups/v1alpha/db.go b/backend/daemon/api/groups/v1alpha/db.go index 64244a94b9..77db7049f6 100644 --- a/backend/daemon/api/groups/v1alpha/db.go +++ b/backend/daemon/api/groups/v1alpha/db.go @@ -36,7 +36,7 @@ func (db *DB) RecordSiteSync(ctx context.Context, baseURL string, pid peer.ID, n nowts := now.Unix() - if err := sqlitex.Exec(conn, qRecordSiteSync(), nil, pid.String(), nowts, ok, nowts, baseURL); err != nil { + if err := sqlitex.Exec(conn, qRecordSiteSync(), nil, pid.String(), nowts, ok, baseURL); err != nil { return err } @@ -51,7 +51,7 @@ var qRecordSiteSync = dqb.Str(` UPDATE remote_sites SET peer_id = :pid, last_sync_time = :now, - last_ok_sync_time = iif(:ok, :now, last_ok_sync_time) + last_ok_sync_time = iif(:ok = 1, :now, last_ok_sync_time) WHERE url = :url; `) @@ -64,6 +64,7 @@ type siteRecord struct { LastSyncOkTime int64 } +// GetSite returns the site record. func (db *DB) GetSite(ctx context.Context, baseURL string) (sr siteRecord, err error) { return sr, db.QueryOne(ctx, qGetSite(), []any{baseURL}, []any{ &sr.URL, @@ -165,13 +166,21 @@ func (db *DB) QueryOne(ctx context.Context, sql string, args []any, outs []any) var count int - return sqlitex.Exec(conn, sql, func(stmt *sqlite.Stmt) error { + if err := sqlitex.Exec(conn, sql, func(stmt *sqlite.Stmt) error { count++ - if count != 1 { - return fmt.Errorf("expected one row, but got more") - } - stmt.Scan(outs...) return nil - }, args...) + }, args...); err != nil { + return err + } + + if count == 0 { + return fmt.Errorf("not found") + } + + if count > 1 { + return fmt.Errorf("expected one record but got %d", count) + } + + return nil } diff --git a/backend/daemon/api/groups/v1alpha/groups.go b/backend/daemon/api/groups/v1alpha/groups.go index 0b6d789039..5e4767d882 100644 --- a/backend/daemon/api/groups/v1alpha/groups.go +++ b/backend/daemon/api/groups/v1alpha/groups.go @@ -14,7 +14,6 @@ import ( "mintter/backend/hlc" "mintter/backend/hyper" "mintter/backend/hyper/hypersql" - "mintter/backend/ipfs" "mintter/backend/mttnet" "mintter/backend/pkg/errutil" "mintter/backend/pkg/future" @@ -29,6 +28,7 @@ import ( "crawshaw.io/sqlite/sqlitex" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/peer" + "github.com/multiformats/go-multiaddr" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" @@ -108,7 +108,7 @@ func (srv *Server) SyncSite(ctx context.Context, siteURL string, interval time.D }() if info.GroupId != sr.GroupID { - return fmt.Errorf("group ID mismatch: remote %s != local %s", info.GroupId, sr.GroupID) + return fmt.Errorf("group ID mismatch: remote %q != local %q", info.GroupId, sr.GroupID) } // Nothing to sync if the site still has the same version since the last time we asked. @@ -321,7 +321,7 @@ func addrInfoFromProto(in *groups.PeerInfo) (ai peer.AddrInfo, err error) { return ai, err } - addrs, err := ipfs.ParseMultiaddrs(in.Addrs) + addrs, err := slicex.MapE(in.Addrs, multiaddr.NewMultiaddr) if err != nil { return ai, fmt.Errorf("failed to parse peer info addrs: %w", err) } @@ -823,8 +823,6 @@ func GetSiteInfoHTTP(ctx context.Context, client *http.Client, siteURL string) ( client = http.DefaultClient } - fmt.Println(siteURL) - if siteURL[len(siteURL)-1] == '/' { return nil, fmt.Errorf("site URL must not have trailing slash: %s", siteURL) } @@ -841,13 +839,14 @@ func GetSiteInfoHTTP(ctx context.Context, client *http.Client, siteURL string) ( return nil, fmt.Errorf("could not contact to provided site [%s]: %w ", requestURL, err) } defer res.Body.Close() - if res.StatusCode < 200 || res.StatusCode > 299 { - return nil, fmt.Errorf("site info url [%s] not working. Status code: %d", requestURL, res.StatusCode) - } data, err := io.ReadAll(res.Body) if err != nil { - return nil, fmt.Errorf("failed to read json body: %w", err) + return nil, fmt.Errorf("failed to read response body: %w", err) + } + + if res.StatusCode < 200 || res.StatusCode > 299 { + return nil, fmt.Errorf("site info url %q not working, status code: %d, response body: %s", requestURL, res.StatusCode, data) } resp := &groups.PublicSiteInfo{} diff --git a/backend/daemon/storage/migrations.go b/backend/daemon/storage/migrations.go index e54357a24a..e4ccb4b883 100644 --- a/backend/daemon/storage/migrations.go +++ b/backend/daemon/storage/migrations.go @@ -97,6 +97,20 @@ var migrations = []migration{ DROP VIEW public_blobs_view; `)) }}, + {Version: "2023-09-21.02", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, sqlfmt(` + DROP TABLE remote_sites; + CREATE TABLE remote_sites ( + url TEXT UNIQUE NOT NULL, + peer_id TEXT NOT NULL DEFAULT (''), + group_id TEXT NOT NULL, + group_version TEXT NOT NULL DEFAULT (''), + last_sync_time INTEGER NOT NULL DEFAULT (0), + last_ok_sync_time INTEGER NOT NULL DEFAULT (0) + ); + DELETE FROM kv WHERE key = 'last_reindex_time'; + `)) + }}, } const ( diff --git a/backend/daemon/storage/schema.gensum b/backend/daemon/storage/schema.gensum index d69cb779ee..f500dc5b76 100644 --- a/backend/daemon/storage/schema.gensum +++ b/backend/daemon/storage/schema.gensum @@ -1,2 +1,2 @@ -srcs: 1b161fb5b046c382f26f234c4bec32ee +srcs: 7176ab3b77037c5713d54897f5ce357c outs: a74e5e1b270e88a4f0c3d5bde6431ee1 diff --git a/backend/daemon/storage/schema.sql b/backend/daemon/storage/schema.sql index a5cb9cc992..0316be7781 100644 --- a/backend/daemon/storage/schema.sql +++ b/backend/daemon/storage/schema.sql @@ -221,12 +221,12 @@ CREATE TABLE remote_sites ( -- Values below are stable and are used to validate -- whether site and group information correspond to each other. url TEXT UNIQUE NOT NULL, - peer_id TEXT NOT NULL, + peer_id TEXT NOT NULL DEFAULT (''), group_id TEXT NOT NULL, -- Values below are updated on each sync and used for caching. - group_version TEXT NOT NULL, - last_sync_time INTEGER NOT NULL, - last_ok_sync_time INTEGER NOT NULL + group_version TEXT NOT NULL DEFAULT (''), + last_sync_time INTEGER NOT NULL DEFAULT (0), + last_ok_sync_time INTEGER NOT NULL DEFAULT (0) ); -- Stores mapping between account public keys diff --git a/backend/daemon/storage/sqlite.go b/backend/daemon/storage/sqlite.go index dace3079a3..e53c13dcb5 100644 --- a/backend/daemon/storage/sqlite.go +++ b/backend/daemon/storage/sqlite.go @@ -92,3 +92,26 @@ func MakeTestDB(t testing.TB) *sqlitex.Pool { require.NoError(t, InitSQLiteSchema(pool)) return pool } + +// SetKV sets a key-value pair in the database. +func SetKV(conn *sqlite.Conn, key, value string, replace bool) error { + if replace { + return sqlitex.Exec(conn, "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?);", nil, key, value) + } + + return sqlitex.Exec(conn, "INSERT INTO kv (key, value) VALUES (?, ?);", nil, key, value) +} + +// GetKV gets a key-value pair from the database. +func GetKV(conn *sqlite.Conn, key string) (string, error) { + var value string + err := sqlitex.Exec(conn, "SELECT value FROM kv WHERE key = ?;", func(stmt *sqlite.Stmt) error { + value = stmt.ColumnText(0) + return nil + }, key) + if err != nil { + return "", err + } + + return value, nil +} diff --git a/backend/genproto/p2p/v1alpha/p2p.pb.go b/backend/genproto/p2p/v1alpha/p2p.pb.go index 991c8947df..eb121709b2 100644 --- a/backend/genproto/p2p/v1alpha/p2p.pb.go +++ b/backend/genproto/p2p/v1alpha/p2p.pb.go @@ -20,91 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type ListBlobsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ListBlobsRequest) Reset() { - *x = ListBlobsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListBlobsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListBlobsRequest) ProtoMessage() {} - -func (x *ListBlobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListBlobsRequest.ProtoReflect.Descriptor instead. -func (*ListBlobsRequest) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{0} -} - -type Blob struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Cid []byte `protobuf:"bytes,1,opt,name=cid,proto3" json:"cid,omitempty"` -} - -func (x *Blob) Reset() { - *x = Blob{} - if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Blob) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Blob) ProtoMessage() {} - -func (x *Blob) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Blob.ProtoReflect.Descriptor instead. -func (*Blob) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{1} -} - -func (x *Blob) GetCid() []byte { - if x != nil { - return x.Cid - } - return nil -} - type HandshakeInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -119,7 +34,7 @@ type HandshakeInfo struct { func (x *HandshakeInfo) Reset() { *x = HandshakeInfo{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[2] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -132,7 +47,7 @@ func (x *HandshakeInfo) String() string { func (*HandshakeInfo) ProtoMessage() {} func (x *HandshakeInfo) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[2] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -145,7 +60,7 @@ func (x *HandshakeInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use HandshakeInfo.ProtoReflect.Descriptor instead. func (*HandshakeInfo) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{2} + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{0} } func (x *HandshakeInfo) GetKeyDelegationCid() []byte { @@ -171,7 +86,7 @@ type ListObjectsRequest struct { func (x *ListObjectsRequest) Reset() { *x = ListObjectsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[3] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -184,7 +99,7 @@ func (x *ListObjectsRequest) String() string { func (*ListObjectsRequest) ProtoMessage() {} func (x *ListObjectsRequest) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[3] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -197,7 +112,7 @@ func (x *ListObjectsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListObjectsRequest.ProtoReflect.Descriptor instead. func (*ListObjectsRequest) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{3} + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{1} } type ListObjectsResponse struct { @@ -211,7 +126,7 @@ type ListObjectsResponse struct { func (x *ListObjectsResponse) Reset() { *x = ListObjectsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[4] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -224,7 +139,7 @@ func (x *ListObjectsResponse) String() string { func (*ListObjectsResponse) ProtoMessage() {} func (x *ListObjectsResponse) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[4] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -237,7 +152,7 @@ func (x *ListObjectsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListObjectsResponse.ProtoReflect.Descriptor instead. func (*ListObjectsResponse) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{4} + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{2} } func (x *ListObjectsResponse) GetObjects() []*Object { @@ -247,32 +162,29 @@ func (x *ListObjectsResponse) GetObjects() []*Object { return nil } -type Object struct { +type ListBlobsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ChangeIds []string `protobuf:"bytes,2,rep,name=change_ids,json=changeIds,proto3" json:"change_ids,omitempty"` } -func (x *Object) Reset() { - *x = Object{} +func (x *ListBlobsRequest) Reset() { + *x = ListBlobsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[5] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Object) String() string { +func (x *ListBlobsRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Object) ProtoMessage() {} +func (*ListBlobsRequest) ProtoMessage() {} -func (x *Object) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[5] +func (x *ListBlobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -283,23 +195,9 @@ func (x *Object) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Object.ProtoReflect.Descriptor instead. -func (*Object) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{5} -} - -func (x *Object) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Object) GetChangeIds() []string { - if x != nil { - return x.ChangeIds - } - return nil +// Deprecated: Use ListBlobsRequest.ProtoReflect.Descriptor instead. +func (*ListBlobsRequest) Descriptor() ([]byte, []int) { + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{3} } // Request Invoice request. @@ -321,7 +219,7 @@ type RequestInvoiceRequest struct { func (x *RequestInvoiceRequest) Reset() { *x = RequestInvoiceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -334,7 +232,7 @@ func (x *RequestInvoiceRequest) String() string { func (*RequestInvoiceRequest) ProtoMessage() {} func (x *RequestInvoiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -347,7 +245,7 @@ func (x *RequestInvoiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestInvoiceRequest.ProtoReflect.Descriptor instead. func (*RequestInvoiceRequest) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{6} + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{4} } func (x *RequestInvoiceRequest) GetAmountSats() int64 { @@ -391,7 +289,7 @@ type RequestInvoiceResponse struct { func (x *RequestInvoiceResponse) Reset() { *x = RequestInvoiceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -404,7 +302,7 @@ func (x *RequestInvoiceResponse) String() string { func (*RequestInvoiceResponse) ProtoMessage() {} func (x *RequestInvoiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -417,7 +315,7 @@ func (x *RequestInvoiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestInvoiceResponse.ProtoReflect.Descriptor instead. func (*RequestInvoiceResponse) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{7} + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{5} } func (x *RequestInvoiceResponse) GetPayReq() string { @@ -427,45 +325,147 @@ func (x *RequestInvoiceResponse) GetPayReq() string { return "" } +type Object struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + ChangeIds []string `protobuf:"bytes,2,rep,name=change_ids,json=changeIds,proto3" json:"change_ids,omitempty"` +} + +func (x *Object) Reset() { + *x = Object{} + if protoimpl.UnsafeEnabled { + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Object) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Object) ProtoMessage() {} + +func (x *Object) ProtoReflect() protoreflect.Message { + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Object.ProtoReflect.Descriptor instead. +func (*Object) Descriptor() ([]byte, []int) { + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{6} +} + +func (x *Object) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Object) GetChangeIds() []string { + if x != nil { + return x.ChangeIds + } + return nil +} + +type Blob struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cid []byte `protobuf:"bytes,1,opt,name=cid,proto3" json:"cid,omitempty"` +} + +func (x *Blob) Reset() { + *x = Blob{} + if protoimpl.UnsafeEnabled { + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Blob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Blob) ProtoMessage() {} + +func (x *Blob) ProtoReflect() protoreflect.Message { + mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Blob.ProtoReflect.Descriptor instead. +func (*Blob) Descriptor() ([]byte, []int) { + return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{7} +} + +func (x *Blob) GetCid() []byte { + if x != nil { + return x.Cid + } + return nil +} + var File_p2p_v1alpha_p2p_proto protoreflect.FileDescriptor var file_p2p_v1alpha_p2p_proto_rawDesc = []byte{ 0x0a, 0x15, 0x70, 0x32, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x70, 0x32, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x22, 0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x10, 0x0a, 0x03, - 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x69, 0x64, 0x22, 0x6d, - 0x0a, 0x0d, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6b, 0x65, 0x79, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x69, 0x64, 0x12, 0x2e, 0x0a, - 0x13, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x22, 0x14, 0x0a, - 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x50, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x37, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x22, 0x6d, 0x0a, 0x0d, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6b, + 0x65, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x69, 0x64, 0x12, + 0x2e, 0x0a, 0x13, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x6b, 0x65, + 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x22, + 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x50, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x94, 0x01, 0x0a, 0x15, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, + 0x73, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x53, 0x61, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x6f, + 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x68, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x70, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x48, 0x61, + 0x73, 0x68, 0x22, 0x31, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x70, 0x61, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, + 0x61, 0x79, 0x52, 0x65, 0x71, 0x22, 0x37, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x64, 0x73, 0x22, 0x94, - 0x01, 0x0a, 0x15, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x5f, 0x73, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x61, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x6d, - 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x21, 0x0a, - 0x0c, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x69, 0x6d, 0x61, 0x67, - 0x65, 0x48, 0x61, 0x73, 0x68, 0x22, 0x31, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x17, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x70, 0x61, 0x79, 0x52, 0x65, 0x71, 0x32, 0x98, 0x03, 0x0a, 0x03, 0x50, 0x32, 0x50, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x64, 0x73, 0x22, 0x18, + 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x69, 0x64, 0x32, 0x98, 0x03, 0x0a, 0x03, 0x50, 0x32, 0x50, 0x12, 0x5b, 0x0a, 0x09, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, @@ -511,25 +511,25 @@ func file_p2p_v1alpha_p2p_proto_rawDescGZIP() []byte { var file_p2p_v1alpha_p2p_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_p2p_v1alpha_p2p_proto_goTypes = []interface{}{ - (*ListBlobsRequest)(nil), // 0: com.mintter.p2p.v1alpha.ListBlobsRequest - (*Blob)(nil), // 1: com.mintter.p2p.v1alpha.Blob - (*HandshakeInfo)(nil), // 2: com.mintter.p2p.v1alpha.HandshakeInfo - (*ListObjectsRequest)(nil), // 3: com.mintter.p2p.v1alpha.ListObjectsRequest - (*ListObjectsResponse)(nil), // 4: com.mintter.p2p.v1alpha.ListObjectsResponse - (*Object)(nil), // 5: com.mintter.p2p.v1alpha.Object - (*RequestInvoiceRequest)(nil), // 6: com.mintter.p2p.v1alpha.RequestInvoiceRequest - (*RequestInvoiceResponse)(nil), // 7: com.mintter.p2p.v1alpha.RequestInvoiceResponse + (*HandshakeInfo)(nil), // 0: com.mintter.p2p.v1alpha.HandshakeInfo + (*ListObjectsRequest)(nil), // 1: com.mintter.p2p.v1alpha.ListObjectsRequest + (*ListObjectsResponse)(nil), // 2: com.mintter.p2p.v1alpha.ListObjectsResponse + (*ListBlobsRequest)(nil), // 3: com.mintter.p2p.v1alpha.ListBlobsRequest + (*RequestInvoiceRequest)(nil), // 4: com.mintter.p2p.v1alpha.RequestInvoiceRequest + (*RequestInvoiceResponse)(nil), // 5: com.mintter.p2p.v1alpha.RequestInvoiceResponse + (*Object)(nil), // 6: com.mintter.p2p.v1alpha.Object + (*Blob)(nil), // 7: com.mintter.p2p.v1alpha.Blob } var file_p2p_v1alpha_p2p_proto_depIdxs = []int32{ - 5, // 0: com.mintter.p2p.v1alpha.ListObjectsResponse.objects:type_name -> com.mintter.p2p.v1alpha.Object - 2, // 1: com.mintter.p2p.v1alpha.P2P.Handshake:input_type -> com.mintter.p2p.v1alpha.HandshakeInfo - 3, // 2: com.mintter.p2p.v1alpha.P2P.ListObjects:input_type -> com.mintter.p2p.v1alpha.ListObjectsRequest - 0, // 3: com.mintter.p2p.v1alpha.P2P.ListBlobs:input_type -> com.mintter.p2p.v1alpha.ListBlobsRequest - 6, // 4: com.mintter.p2p.v1alpha.P2P.RequestInvoice:input_type -> com.mintter.p2p.v1alpha.RequestInvoiceRequest - 2, // 5: com.mintter.p2p.v1alpha.P2P.Handshake:output_type -> com.mintter.p2p.v1alpha.HandshakeInfo - 4, // 6: com.mintter.p2p.v1alpha.P2P.ListObjects:output_type -> com.mintter.p2p.v1alpha.ListObjectsResponse - 1, // 7: com.mintter.p2p.v1alpha.P2P.ListBlobs:output_type -> com.mintter.p2p.v1alpha.Blob - 7, // 8: com.mintter.p2p.v1alpha.P2P.RequestInvoice:output_type -> com.mintter.p2p.v1alpha.RequestInvoiceResponse + 6, // 0: com.mintter.p2p.v1alpha.ListObjectsResponse.objects:type_name -> com.mintter.p2p.v1alpha.Object + 0, // 1: com.mintter.p2p.v1alpha.P2P.Handshake:input_type -> com.mintter.p2p.v1alpha.HandshakeInfo + 1, // 2: com.mintter.p2p.v1alpha.P2P.ListObjects:input_type -> com.mintter.p2p.v1alpha.ListObjectsRequest + 3, // 3: com.mintter.p2p.v1alpha.P2P.ListBlobs:input_type -> com.mintter.p2p.v1alpha.ListBlobsRequest + 4, // 4: com.mintter.p2p.v1alpha.P2P.RequestInvoice:input_type -> com.mintter.p2p.v1alpha.RequestInvoiceRequest + 0, // 5: com.mintter.p2p.v1alpha.P2P.Handshake:output_type -> com.mintter.p2p.v1alpha.HandshakeInfo + 2, // 6: com.mintter.p2p.v1alpha.P2P.ListObjects:output_type -> com.mintter.p2p.v1alpha.ListObjectsResponse + 7, // 7: com.mintter.p2p.v1alpha.P2P.ListBlobs:output_type -> com.mintter.p2p.v1alpha.Blob + 5, // 8: com.mintter.p2p.v1alpha.P2P.RequestInvoice:output_type -> com.mintter.p2p.v1alpha.RequestInvoiceResponse 5, // [5:9] is the sub-list for method output_type 1, // [1:5] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name @@ -544,7 +544,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } if !protoimpl.UnsafeEnabled { file_p2p_v1alpha_p2p_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListBlobsRequest); i { + switch v := v.(*HandshakeInfo); i { case 0: return &v.state case 1: @@ -556,7 +556,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Blob); i { + switch v := v.(*ListObjectsRequest); i { case 0: return &v.state case 1: @@ -568,7 +568,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HandshakeInfo); i { + switch v := v.(*ListObjectsResponse); i { case 0: return &v.state case 1: @@ -580,7 +580,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListObjectsRequest); i { + switch v := v.(*ListBlobsRequest); i { case 0: return &v.state case 1: @@ -592,7 +592,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListObjectsResponse); i { + switch v := v.(*RequestInvoiceRequest); i { case 0: return &v.state case 1: @@ -604,7 +604,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Object); i { + switch v := v.(*RequestInvoiceResponse); i { case 0: return &v.state case 1: @@ -616,7 +616,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestInvoiceRequest); i { + switch v := v.(*Object); i { case 0: return &v.state case 1: @@ -628,7 +628,7 @@ func file_p2p_v1alpha_p2p_proto_init() { } } file_p2p_v1alpha_p2p_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestInvoiceResponse); i { + switch v := v.(*Blob); i { case 0: return &v.state case 1: diff --git a/backend/hyper/hypersql/queries.manual.go b/backend/hyper/hypersql/queries.manual.go index 1e0bdc7570..f6971ccc92 100644 --- a/backend/hyper/hypersql/queries.manual.go +++ b/backend/hyper/hypersql/queries.manual.go @@ -166,7 +166,8 @@ func SitesInsertOrIgnore(conn *sqlite.Conn, baseURL, groupID string) error { } var qSitesInsertOrIgnore = dqb.Str(` - INSERT OR IGNORE INTO remote_sites (url, group_id) VALUES (?, ?); + INSERT INTO remote_sites (url, group_id) VALUES (?, ?) + ON CONFLICT (url) DO NOTHING; `) // AccountsInsertOrIgnore inserts an account if it doesn't exist. diff --git a/backend/pkg/debugx/debugx.go b/backend/pkg/debugx/debugx.go new file mode 100644 index 0000000000..29a2122308 --- /dev/null +++ b/backend/pkg/debugx/debugx.go @@ -0,0 +1,27 @@ +// Package debugx provides simple debugging facilities. +// It's not named debug to avoid name clash with the stdlib debug package. +// It's a separate package to allow easily grep-ing for debug statements in the codebase. +package debugx + +import ( + "fmt" + + "github.com/sanity-io/litter" +) + +var dumpCfg = litter.Config + +// Re-exporting common debugging functions from other packages. +var ( + Print = fmt.Print + Println = fmt.Println + Printf = fmt.Printf + Dump = dumpCfg.Dump +) + +// DumpAll dumps all the values to stdout with private fields. +func DumpAll(vv ...any) { + cfg := dumpCfg + cfg.HidePrivateFields = true + cfg.Dump(vv...) +} diff --git a/backend/pkg/dqb/dqb.go b/backend/pkg/dqb/dqb.go index cc3796ce0b..b2d1dbd397 100644 --- a/backend/pkg/dqb/dqb.go +++ b/backend/pkg/dqb/dqb.go @@ -6,7 +6,6 @@ package dqb import ( "context" "fmt" - "os" "sync" "crawshaw.io/sqlite/sqlitex" @@ -22,8 +21,6 @@ func Q(fn func() string) LazyQuery { // Str returns a memoized string query that will be formatted lazily. func Str(s string) LazyQuery { - fmt.Println(os.Args) - return GlobalQueries.Str(s) } diff --git a/backend/pkg/slicex/slicex.go b/backend/pkg/slicex/slicex.go index a9157bd95c..0c3a233562 100644 --- a/backend/pkg/slicex/slicex.go +++ b/backend/pkg/slicex/slicex.go @@ -2,6 +2,8 @@ // that are not found in the stdlib slices package. package slicex +import "fmt" + // Map applies a map function to each element of the slice // and produces a new slice with (possibly) transformed value. func Map[In any, Out any](in []In, fn func(In) Out) []Out { @@ -12,6 +14,19 @@ func Map[In any, Out any](in []In, fn func(In) Out) []Out { return out } +// MapE applies a map function that might return an error. +func MapE[In any, Out any](in []In, fn func(In) (Out, error)) ([]Out, error) { + out := make([]Out, len(in)) + for i, v := range in { + var err error + out[i], err = fn(v) + if err != nil { + return nil, fmt.Errorf("failed to map element %v to type %T: %w", v, *(new(Out)), err) + } + } + return out, nil +} + // MapSet is a set-like map. type MapSet[T comparable] map[T]struct{} diff --git a/backend/pkg/sqlitedbg/sqlitedbg.go b/backend/pkg/sqlitedbg/sqlitedbg.go index 5bf346e740..b5aefd6c33 100644 --- a/backend/pkg/sqlitedbg/sqlitedbg.go +++ b/backend/pkg/sqlitedbg/sqlitedbg.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "fmt" "io" + "os" "text/tabwriter" "crawshaw.io/sqlite" @@ -14,6 +15,10 @@ import ( // Exec a query and print the results into w. func Exec[T *sqlitex.Pool | *sqlite.Conn](db T, w io.Writer, query string) { + if w == nil { + w = os.Stdout + } + var conn *sqlite.Conn switch v := any(db).(type) { diff --git a/proto/p2p/v1alpha/go.gensum b/proto/p2p/v1alpha/go.gensum index 522ffe39b3..19c9215516 100644 --- a/proto/p2p/v1alpha/go.gensum +++ b/proto/p2p/v1alpha/go.gensum @@ -1,2 +1,2 @@ -srcs: 48a6e9c877903c6cbdf4145a7cb43121 -outs: 424d5f89db259489f5776e2668b7b649 +srcs: e5865f4517a8b8ae9518f44c6199ae0b +outs: b6d7a20d07bd8163c8ec592326f9a26d