Merge branch 'sync-prototype'

This commit is contained in:
mcrakhman 2022-08-05 21:06:13 +02:00
commit 7eb965977a
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
69 changed files with 7901 additions and 258 deletions

View File

@ -16,18 +16,23 @@ export PATH=$(GOPATH)/bin:$(shell echo $$PATH)
protos-go: protos-go:
@echo 'Generating protobuf packages (Go)...' @echo 'Generating protobuf packages (Go)...'
# Uncomment if needed # Uncomment if needed
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types)
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types)
@$(eval ROOT_PKG := pkg) @$(eval ROOT_PKG := pkg)
@$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1) @$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1)
@$(eval P_TREE_STORAGE_PATH_PB := $(ROOT_PKG)/acl/treestorage/treepb) @$(eval P_TREE_STORAGE_PATH_PB := $(ROOT_PKG)/acl/treestorage/treepb)
@$(eval P_ACL_CHANGES_PATH_PB := $(ROOT_PKG)/acl/aclchanges/aclpb) @$(eval P_ACL_CHANGES_PATH_PB := $(ROOT_PKG)/acl/aclchanges/aclpb)
@$(eval P_PLAINTEXT_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges/testchangepb) @$(eval P_PLAINTEXT_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges/testchangepb)
@$(eval P_SYNC_CHANGES_PATH_PB := syncproto)
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types)
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types)
@$(eval P_ACL_CHANGES := M$(P_ACL_CHANGES_PATH_PB)/protos/aclchanges.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_CHANGES_PATH_PB))
@$(eval P_TREE_CHANGES := M$(P_TREE_STORAGE_PATH_PB)/protos/tree.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_TREE_STORAGE_PATH_PB))
# use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT)) # use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT))
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto; mv $(P_ACL_CHANGES_PATH_PB)/protos/*.go $(P_ACL_CHANGES_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto; mv $(P_ACL_CHANGES_PATH_PB)/protos/*.go $(P_ACL_CHANGES_PATH_PB)
$(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_STORAGE_PATH_PB)/protos/*.proto; mv $(P_TREE_STORAGE_PATH_PB)/protos/*.go $(P_TREE_STORAGE_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_STORAGE_PATH_PB)/protos/*.proto; mv $(P_TREE_STORAGE_PATH_PB)/protos/*.go $(P_TREE_STORAGE_PATH_PB)
$(GOGO_START) protoc --gogofaster_out=:. $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.proto; mv $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.go $(P_PLAINTEXT_CHANGES_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.proto; mv $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.go $(P_PLAINTEXT_CHANGES_PATH_PB)
$(eval PKGMAP := $$(P_ACL_CHANGES),$$(P_TREE_CHANGES))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP),plugins=grpc:. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
build: build:
@$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app)) @$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app))

View File

@ -7,7 +7,20 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config" "github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/api"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/dialer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/rpc/server"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/secure"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/document"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/requesthandler"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
"go.uber.org/zap" "go.uber.org/zap"
"net/http"
_ "net/http/pprof"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
@ -34,6 +47,12 @@ func main() {
return return
} }
if debug, ok := os.LookupEnv("ANYPROF"); ok && debug != "" {
go func() {
http.ListenAndServe(debug, nil)
}()
}
// create app // create app
ctx := context.Background() ctx := context.Background()
a := new(app.App) a := new(app.App)
@ -50,7 +69,7 @@ func main() {
// start app // start app
if err := a.Start(ctx); err != nil { if err := a.Start(ctx); err != nil {
log.Error("can't start app", zap.Error(err)) log.Fatal("can't start app", zap.Error(err))
} }
log.Info("app started", zap.String("version", a.Version())) log.Info("app started", zap.String("version", a.Version()))
@ -68,8 +87,20 @@ func main() {
} else { } else {
log.Info("goodbye!") log.Info("goodbye!")
} }
time.Sleep(time.Second / 3)
} }
func Bootstrap(a *app.App) { func Bootstrap(a *app.App) {
//a.Register(mycomponent.New()) a.Register(account.New()).
Register(node.New()).
Register(secure.New()).
Register(server.New()).
Register(dialer.New()).
Register(pool.NewPool()).
//Register(&example.Example{})
Register(document.New()).
Register(message.New()).
Register(requesthandler.New()).
Register(treecache.New()).
Register(api.New())
} }

136
cmd/nodesgen/gen.go Normal file
View File

@ -0,0 +1,136 @@
package main
import (
"flag"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/peer"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
)
var (
flagNodeMap = flag.String("n", "cmd/nodesgen/nodemap.yml", "path to nodes map file")
flagEtcPath = flag.String("e", "etc", "path to etc directory")
)
type NodesMap struct {
Nodes []struct {
Addresses []string `yaml:"grpcAddresses"`
APIPort string `yaml:"apiPort"`
} `yaml:"nodes"`
}
func main() {
nodesMap := &NodesMap{}
data, err := ioutil.ReadFile(*flagNodeMap)
if err != nil {
panic(err)
}
err = yaml.Unmarshal(data, nodesMap)
if err != nil {
panic(err)
}
flag.Parse()
var configs []config.Config
var nodes []config.Node
for _, n := range nodesMap.Nodes {
cfg, err := genConfig(n.Addresses, n.APIPort)
if err != nil {
panic(fmt.Sprintf("could not generate the config file: %s", err.Error()))
}
configs = append(configs, cfg)
node := config.Node{
PeerId: cfg.Account.PeerId,
Address: cfg.GrpcServer.ListenAddrs[0],
SigningKey: cfg.Account.SigningKey,
EncryptionKey: cfg.Account.EncryptionKey,
}
nodes = append(nodes, node)
}
for idx := range configs {
configs[idx].Nodes = nodes
}
// saving configs
configsPath := fmt.Sprintf("%s/configs", *flagEtcPath)
createDir := func() {
err := os.Mkdir(configsPath, os.ModePerm)
if err != nil {
panic(fmt.Sprintf("failed to create the configs directory: %v", err))
}
}
if _, err := os.Stat(configsPath); os.IsNotExist(err) {
createDir()
} else {
err = os.RemoveAll(configsPath)
if err != nil {
panic(fmt.Sprintf("failed to remove the configs directory: %v", err))
}
createDir()
}
for _, cfg := range configs {
path := fmt.Sprintf("%s/%s.yml", configsPath, cfg.Account.PeerId)
bytes, err := yaml.Marshal(cfg)
if err != nil {
panic(fmt.Sprintf("could not marshal the keys: %v", err))
}
err = os.WriteFile(path, bytes, os.ModePerm)
if err != nil {
panic(fmt.Sprintf("could not write the config to file: %v", err))
}
}
}
func genConfig(addresses []string, apiPort string) (config.Config, error) {
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
if err != nil {
return config.Config{}, err
}
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil {
return config.Config{}, err
}
encKeyDecoder := encryptionkey.NewRSAPrivKeyDecoder()
signKeyDecoder := signingkey.NewEDPrivKeyDecoder()
encEncKey, err := encKeyDecoder.EncodeToString(encKey)
if err != nil {
return config.Config{}, err
}
encSignKey, err := signKeyDecoder.EncodeToString(signKey)
if err != nil {
return config.Config{}, err
}
peerID, err := peer.IDFromSigningPubKey(signKey.GetPublic())
if err != nil {
return config.Config{}, err
}
return config.Config{
Anytype: config.Anytype{SwarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"},
GrpcServer: config.GrpcServer{
ListenAddrs: addresses,
TLS: false,
},
Account: config.Account{
PeerId: peerID.String(),
SigningKey: encSignKey,
EncryptionKey: encEncKey,
},
APIServer: config.APIServer{
Port: apiPort,
},
}, nil
}

9
cmd/nodesgen/nodemap.yml Normal file
View File

@ -0,0 +1,9 @@
nodes:
- grpcAddresses:
- "127.0.0.1:4430"
- "127.0.0.1:4431"
apiPort: "8080"
- grpcAddresses:
- "127.0.0.1:4432"
- "127.0.0.1:4433"
apiPort: "8081"

7
config/account.go Normal file
View File

@ -0,0 +1,7 @@
package config
type Account struct {
PeerId string `yaml:"peerId"`
SigningKey string `yaml:"signingKey"`
EncryptionKey string `yaml:"encryptionKey"`
}

5
config/api.go Normal file
View File

@ -0,0 +1,5 @@
package config
type APIServer struct {
Port string `yaml:"port"`
}

View File

@ -26,6 +26,9 @@ func NewFromFile(path string) (c *Config, err error) {
type Config struct { type Config struct {
Anytype Anytype `yaml:"anytype"` Anytype Anytype `yaml:"anytype"`
GrpcServer GrpcServer `yaml:"grpcServer"` GrpcServer GrpcServer `yaml:"grpcServer"`
Account Account `yaml:"account"`
APIServer APIServer `yaml:"apiServer"`
Nodes []Node `yaml:"nodes"`
} }
func (c *Config) Init(ctx context.Context, a *app.App) (err error) { func (c *Config) Init(ctx context.Context, a *app.App) (err error) {

View File

@ -2,4 +2,5 @@ package config
type GrpcServer struct { type GrpcServer struct {
ListenAddrs []string `yaml:"listenAddrs"` ListenAddrs []string `yaml:"listenAddrs"`
TLS bool `yaml:"tls"`
} }

8
config/nodes.go Normal file
View File

@ -0,0 +1,8 @@
package config
type Node struct {
PeerId string `yaml:"peerId"`
Address string `yaml:"address"`
SigningKey string `yaml:"signingKey"`
EncryptionKey string `yaml:"encryptionKey"`
}

14
config/peer.go Normal file
View File

@ -0,0 +1,14 @@
package config
type PeerList struct {
MyId struct {
PeerId string `yaml:"peerId"`
PrivKey string `yaml:"privKey"`
} `yaml:"myId"`
Remote []PeerRemote `yaml:"remote"`
}
type PeerRemote struct {
PeerId string `yaml:"peerId"`
Addr string `yaml:"addr"`
}

16
etc/config.1.yml Normal file
View File

@ -0,0 +1,16 @@
anytype:
swarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"
grpcServer:
listenAddrs:
- "127.0.0.1:4431"
peerList:
myId:
peerId: "12D3KooWA4FLWvrMbCtp2MbzKcC5RRN7HqxxBxPcSADFfzrGiW3U"
privKey: "InCGjb55V9+jj2PebUExUuwrpOIBc4hmgk2dSqyk3k4DjmgrdoNVuFe7xCFaFdUVb0RJYj6A+OTp2yXASTmq2w=="
remote:
- peerId: "12D3KooWHJpSEMQUZCyK8TK181LhjzntWjKfXDr7MWks9cw41R2C"
addr: "127.0.0.1:4430"
- peerId: "12D3KooWK6c1CPLL4Bvjim9A9SDRmehy12hYjbqX1VASHKfH7W7H"
addr: "127.0.0.1:4432"

16
etc/config.2.yml Normal file
View File

@ -0,0 +1,16 @@
anytype:
swarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec"
grpcServer:
listenAddrs:
- "127.0.0.1:4432"
peerList:
myId:
peerId: "12D3KooWK6c1CPLL4Bvjim9A9SDRmehy12hYjbqX1VASHKfH7W7H"
privKey: "jynYZBgtM4elT+6e7M5UERTJCZgUd3hDdmQjCqTpApyJ4h53V6TQan4Ru4OXqz+91rCLjpIVdphhaB0l+TvNsA=="
remote:
- peerId: "12D3KooWA4FLWvrMbCtp2MbzKcC5RRN7HqxxBxPcSADFfzrGiW3U"
addr: "127.0.0.1:4431"
- peerId: "12D3KooWHJpSEMQUZCyK8TK181LhjzntWjKfXDr7MWks9cw41R2C"
addr: "127.0.0.1:4430"

View File

@ -1,6 +1,22 @@
anytype: anytype:
swarmKey: "/key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec" swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
grpcServer: grpcServer:
listenAddrs: listenAddrs:
- ":443" - 127.0.0.1:4430
- 127.0.0.1:4431
tls: false
account:
peerId: 12D3KooWMHuhZgK2skkLrvL51QQTXaXQKYy2QqfvPNBFnzR2ubA1
signingKey: 3id6ddLcoNoe9rDgGM88ET8T6TnvHm5GFqFdN6kBzn7Q8d6VUGgjeT59CNWFiaofdeRnHBvX2A5ZacMXvfwaYEFuCbug
encryptionKey: JgG4CcCbae1qEpe7mKpBzsHjZhXUmDSNVNX2B1gxFZsJyMX4V6kBQUott9zRWyeXaW1ZmpzuxDXnwSQpAnNurhXyGa9iQaAPqzY9A9VWBPD33Yy1eW7TRuVemzToh8jJQKQKnZNbF8ucTWV9qahusKzyvN8uyhrqoW2tAPfA9S3E3ognCuqbLSW6yjE2rBKayvyS1BVwzjSd6FZK4DDyjfU3pbEVjut3wytGEAn9af6sNMmyCnf2MX5vLovWs9rU8av61wD4z7HTsXyGFx4K75N4Go249Hpe9SKAT6HxhRc3yvj63krPLiQV5yMuH2UeMUXBDekUQyNmBEdn9wrur7mLqB67Bc6tcc2PP8XApBCdWJHvHjN4FktSpaG5vbCqoZbLD1oCbk36q2x9s6XM8pydVqD1J9P3nTbfgMb5pJCTFjNtgKeuKv6wjfJeA9jF1VhcJQisfsahgv9MvZ9M8FJpZTq1zKUhYDCRnZxUkraoMS5yNNVdDzaUckKEDthqik7BMWCWT79vq7uVgMwEvGwGi76gtoMg1159bbPMLZ4bdPVfhH2S9QjPrzQfwZSrzB2YeVPjWpaXDeLDity5H8n1NK2oniAQR6gE71n81neSptsuhV6o6QpQ89AU8y57XmEsou4VEryn8vUxBHhULLxrLNUouxyWamCeFiDjk5cSN6koQsf9BYKSNTPFTrwjTKForDokMhcPdMtFktKwjv7u9UEGcY4MKvNzZZkc77gHiP8bqVtdNNoLpTFUC5SZ9i7bKdHvK12HpSy7yzzPeMXJ9UwhLxkok1g81ngTbN1yxRhvYXyHZFtguCR9kvGojDjka91MTBtk551qDw9eCn2xZT9U8jqzBCjdpvSg3mRWKMPnYAGB7m7u1ye165wyGFvzcHAx3vtXjxAqLUeKYZCjv2m6V9D2Y4qH1TQNddWqH14T1JVMis971UCH9Ddpj6a3387oUnufD1P6HZN2ieJCvptrmbGVvxJYYSvmVf1dkwbtqurDRNWD7TJ7gf6iqSP549C9bxP4GpLt3ygjHmMtcuUzstBuztvunJUnQhfnJxqU6LjRdsFzm53wGWgXNxab7ZvQcPyLwsevn1b98FGPnVpS5iY4LjmqW4ugrC6HgrbsjrXiKzR1yZKhLQkCbLzPoaHb8iB5iBnCr7d4yf5CtfpFRqgoqMFdK5LNZYmDX4HzUKN6A7wC3gGiSRFTLcgGZeSMkB5Pa61CZBU7WCQgFxykycE9HRA7PiQa496GWDCV15teToCpFRsAa6jDmR1MGXPeLRqQgve49VXnQN5FL7c1VuEv5SWjeTuCnMB47DJKBaP7eKJNKgLwETALzSCMF3nRiRgeb15kfoS4BbrJ5yupjrvwmbmvNg1AYFFS5sYNWft7K8v87wQvBakRtGP71Kp8NX77XFtu6xdB7sR6jpfC6qJPyB9akWNXgCrWy9kE4ih42gwAZdUugNZ9YtEsgRM3pwb6qJhkAPyEJtrxrja859PCAgqPSQiPQN33PaMkgQ6HJknu8CrjKRiXAycZ16KLUkHV64TNhEjPTcX1a7rqpD131AYMWX8d7CCdc9Ys7RUb6BwguuNSh8rJK3x4AkMDSUsaE8ynKvpC7RXZpJ9Nxfhd
apiServer:
port: "8080"
nodes:
- peerId: 12D3KooWMHuhZgK2skkLrvL51QQTXaXQKYy2QqfvPNBFnzR2ubA1
address: 127.0.0.1:4430
signingKey: 3id6ddLcoNoe9rDgGM88ET8T6TnvHm5GFqFdN6kBzn7Q8d6VUGgjeT59CNWFiaofdeRnHBvX2A5ZacMXvfwaYEFuCbug
encryptionKey: JgG4CcCbae1qEpe7mKpBzsHjZhXUmDSNVNX2B1gxFZsJyMX4V6kBQUott9zRWyeXaW1ZmpzuxDXnwSQpAnNurhXyGa9iQaAPqzY9A9VWBPD33Yy1eW7TRuVemzToh8jJQKQKnZNbF8ucTWV9qahusKzyvN8uyhrqoW2tAPfA9S3E3ognCuqbLSW6yjE2rBKayvyS1BVwzjSd6FZK4DDyjfU3pbEVjut3wytGEAn9af6sNMmyCnf2MX5vLovWs9rU8av61wD4z7HTsXyGFx4K75N4Go249Hpe9SKAT6HxhRc3yvj63krPLiQV5yMuH2UeMUXBDekUQyNmBEdn9wrur7mLqB67Bc6tcc2PP8XApBCdWJHvHjN4FktSpaG5vbCqoZbLD1oCbk36q2x9s6XM8pydVqD1J9P3nTbfgMb5pJCTFjNtgKeuKv6wjfJeA9jF1VhcJQisfsahgv9MvZ9M8FJpZTq1zKUhYDCRnZxUkraoMS5yNNVdDzaUckKEDthqik7BMWCWT79vq7uVgMwEvGwGi76gtoMg1159bbPMLZ4bdPVfhH2S9QjPrzQfwZSrzB2YeVPjWpaXDeLDity5H8n1NK2oniAQR6gE71n81neSptsuhV6o6QpQ89AU8y57XmEsou4VEryn8vUxBHhULLxrLNUouxyWamCeFiDjk5cSN6koQsf9BYKSNTPFTrwjTKForDokMhcPdMtFktKwjv7u9UEGcY4MKvNzZZkc77gHiP8bqVtdNNoLpTFUC5SZ9i7bKdHvK12HpSy7yzzPeMXJ9UwhLxkok1g81ngTbN1yxRhvYXyHZFtguCR9kvGojDjka91MTBtk551qDw9eCn2xZT9U8jqzBCjdpvSg3mRWKMPnYAGB7m7u1ye165wyGFvzcHAx3vtXjxAqLUeKYZCjv2m6V9D2Y4qH1TQNddWqH14T1JVMis971UCH9Ddpj6a3387oUnufD1P6HZN2ieJCvptrmbGVvxJYYSvmVf1dkwbtqurDRNWD7TJ7gf6iqSP549C9bxP4GpLt3ygjHmMtcuUzstBuztvunJUnQhfnJxqU6LjRdsFzm53wGWgXNxab7ZvQcPyLwsevn1b98FGPnVpS5iY4LjmqW4ugrC6HgrbsjrXiKzR1yZKhLQkCbLzPoaHb8iB5iBnCr7d4yf5CtfpFRqgoqMFdK5LNZYmDX4HzUKN6A7wC3gGiSRFTLcgGZeSMkB5Pa61CZBU7WCQgFxykycE9HRA7PiQa496GWDCV15teToCpFRsAa6jDmR1MGXPeLRqQgve49VXnQN5FL7c1VuEv5SWjeTuCnMB47DJKBaP7eKJNKgLwETALzSCMF3nRiRgeb15kfoS4BbrJ5yupjrvwmbmvNg1AYFFS5sYNWft7K8v87wQvBakRtGP71Kp8NX77XFtu6xdB7sR6jpfC6qJPyB9akWNXgCrWy9kE4ih42gwAZdUugNZ9YtEsgRM3pwb6qJhkAPyEJtrxrja859PCAgqPSQiPQN33PaMkgQ6HJknu8CrjKRiXAycZ16KLUkHV64TNhEjPTcX1a7rqpD131AYMWX8d7CCdc9Ys7RUb6BwguuNSh8rJK3x4AkMDSUsaE8ynKvpC7RXZpJ9Nxfhd
- peerId: 12D3KooWT3c7Y5zvWhhjSxd5Ve3GKZi6WCsG6JHxcxgXixRFdBbw
address: 127.0.0.1:4432
signingKey: 3iiLPj6wMUQpPwTBNZcUgkbXub1jumg4AEV9LfMyFHZVc84GLyAjVbVvH6EAGhcNrxRxL82aW4BimhDZCpLsRCqx5vwj
encryptionKey: JgG4CcCbae1qEpe7mKXzp7m5hNc56SSyZd9DwUaEStKJrq7RToAC2Vgd3i6hKRwa58zCWeN6Wjc3o6qrdKPEPRvcyEPysamajVo5mdQiUgWAmr97pGEsyjuRjQoC2GY2LvLiEQxEgwFgJxKGMHMiaWMtDfxCDUaDEm4bu5RdMhqRZekAWho6c3WoEeruSr14iX1TrocFNfBkBY7CjEw8kcywXCTNgtvhb2Qiwgj5AxEF4wyw4bzaNA9ctXb1hoHPFVMu6C51pkFY7jUD9zwyH3ukgnAewkGAcPNbKmaTAtMosKRVaAN97mAwXh2VRt1hWmRvVk7r76EjnVKhD4vbsKZc56RVcHTVWRVdhU7FGyPsiE5rSQAz1JQGYzxnZpX7EG77CyrmUGyfueVfRHhwY2oq8A4uQCRaQxSaJHYLowjXSxh8DQ2V6MTqyzti32C27utBYdHzLVCJSGkmdzGwrFcHqsq7nLDxmvJVErPvyReixEe8kFmqopJ3e6LLm8WdYw9K6JYBjXnEfwPzm7Von9sf3dcaGDUHYfttMyeke7fAXJkvPRje69hYVyzdQGAauuojzGkkvQWCSMK1KCMNMznRaPDCNvofrQhYrub24WhmwpKhorufdfW8Cb4T6reBDCtaWVsbuinjtL6F6Sui5aYHJFLJ6e4pPewr1P4EuZYRbMBZwN5KvDLhTGLBuBnaTqUUdF6bj2U22NoRYMogiHiftqKqiexKNDXX1Zg9RQEvxgjuVo6SBW42mVEA8agrLhruRqCmiduJxVrfqLNGeYXHXrcmMEgW7uosJbPXvTcfRvdFWS1ov7oSALvj6vhDQ28Yi9D2ETNdNsfVWAFQuwvPpW7CHQGXTitprVbqH8JYxNZuGygcLmr5efbB22Vzu4ntd1HoraQpG12qeDEUA7tXYUpoYyuSdWwKPjSAMtaQcCSfVrhKQHQuKJargrVrez8vjWuwLfvSucV7ZHe7gjqvYgULdE1ubRCRSd7DuLjEN2Vd6obzV2c3MRet7ZSf4Sp88WM5AuTyW7BjArBc4S3gUQ8rYaiZ8Tu7NCxkEzbFwWRaemZkwfvcsX3XxqjyF37tFSGkEqE5kuBvpZW72675LkDffj7kH1zA8yE6dVujJjWsNYVFJWndUtz5Vy2KCdZAbBgq19q4AtsxWPodU2N3yZXzFAFAzTrxS6V4P7Scpdau1avgRvHLcBQPunA37xaYMy8YMifJwtmRY25mnAQwZAk3eANk7tXwZd58SDnciLNvARJvwKzTQBXcshkwyy52SX8XmXDJsPnRLaHmiYBJ63Yzr5XpZuuAtxb9qrWG2NHCNxfomHokWacV1hjZPPd6ZxT1FuRozB6Qt2NLcyqY7bnTcQJb1jPUaTAGXXCR8WVmmmYo2fDQe8CdBmgyPvbzNTEJUyScBz4RdycB5PZap4SurJCWtHbuMyQbQUB6jJgURDstfXS5Akfe4oruNq9rnYcNtnsDJPtrhXHBqzDizmf1BDxR5FB2RCxzCgeAfg8WQ1Ug9PVAGTzob6ZqCrGXzWXEUniZnf1vjr7QhGKBYXEX9SWDoSMUpP4FreVDTnx15ijRZTV3p8xG5fE9e36TnugRVvTyq7XzmyPBjW2r66f1bior

View File

@ -0,0 +1,22 @@
anytype:
swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
grpcServer:
listenAddrs:
- 127.0.0.1:4430
- 127.0.0.1:4431
tls: false
account:
peerId: 12D3KooWMHuhZgK2skkLrvL51QQTXaXQKYy2QqfvPNBFnzR2ubA1
signingKey: 3id6ddLcoNoe9rDgGM88ET8T6TnvHm5GFqFdN6kBzn7Q8d6VUGgjeT59CNWFiaofdeRnHBvX2A5ZacMXvfwaYEFuCbug
encryptionKey: JgG4CcCbae1qEpe7mKpBzsHjZhXUmDSNVNX2B1gxFZsJyMX4V6kBQUott9zRWyeXaW1ZmpzuxDXnwSQpAnNurhXyGa9iQaAPqzY9A9VWBPD33Yy1eW7TRuVemzToh8jJQKQKnZNbF8ucTWV9qahusKzyvN8uyhrqoW2tAPfA9S3E3ognCuqbLSW6yjE2rBKayvyS1BVwzjSd6FZK4DDyjfU3pbEVjut3wytGEAn9af6sNMmyCnf2MX5vLovWs9rU8av61wD4z7HTsXyGFx4K75N4Go249Hpe9SKAT6HxhRc3yvj63krPLiQV5yMuH2UeMUXBDekUQyNmBEdn9wrur7mLqB67Bc6tcc2PP8XApBCdWJHvHjN4FktSpaG5vbCqoZbLD1oCbk36q2x9s6XM8pydVqD1J9P3nTbfgMb5pJCTFjNtgKeuKv6wjfJeA9jF1VhcJQisfsahgv9MvZ9M8FJpZTq1zKUhYDCRnZxUkraoMS5yNNVdDzaUckKEDthqik7BMWCWT79vq7uVgMwEvGwGi76gtoMg1159bbPMLZ4bdPVfhH2S9QjPrzQfwZSrzB2YeVPjWpaXDeLDity5H8n1NK2oniAQR6gE71n81neSptsuhV6o6QpQ89AU8y57XmEsou4VEryn8vUxBHhULLxrLNUouxyWamCeFiDjk5cSN6koQsf9BYKSNTPFTrwjTKForDokMhcPdMtFktKwjv7u9UEGcY4MKvNzZZkc77gHiP8bqVtdNNoLpTFUC5SZ9i7bKdHvK12HpSy7yzzPeMXJ9UwhLxkok1g81ngTbN1yxRhvYXyHZFtguCR9kvGojDjka91MTBtk551qDw9eCn2xZT9U8jqzBCjdpvSg3mRWKMPnYAGB7m7u1ye165wyGFvzcHAx3vtXjxAqLUeKYZCjv2m6V9D2Y4qH1TQNddWqH14T1JVMis971UCH9Ddpj6a3387oUnufD1P6HZN2ieJCvptrmbGVvxJYYSvmVf1dkwbtqurDRNWD7TJ7gf6iqSP549C9bxP4GpLt3ygjHmMtcuUzstBuztvunJUnQhfnJxqU6LjRdsFzm53wGWgXNxab7ZvQcPyLwsevn1b98FGPnVpS5iY4LjmqW4ugrC6HgrbsjrXiKzR1yZKhLQkCbLzPoaHb8iB5iBnCr7d4yf5CtfpFRqgoqMFdK5LNZYmDX4HzUKN6A7wC3gGiSRFTLcgGZeSMkB5Pa61CZBU7WCQgFxykycE9HRA7PiQa496GWDCV15teToCpFRsAa6jDmR1MGXPeLRqQgve49VXnQN5FL7c1VuEv5SWjeTuCnMB47DJKBaP7eKJNKgLwETALzSCMF3nRiRgeb15kfoS4BbrJ5yupjrvwmbmvNg1AYFFS5sYNWft7K8v87wQvBakRtGP71Kp8NX77XFtu6xdB7sR6jpfC6qJPyB9akWNXgCrWy9kE4ih42gwAZdUugNZ9YtEsgRM3pwb6qJhkAPyEJtrxrja859PCAgqPSQiPQN33PaMkgQ6HJknu8CrjKRiXAycZ16KLUkHV64TNhEjPTcX1a7rqpD131AYMWX8d7CCdc9Ys7RUb6BwguuNSh8rJK3x4AkMDSUsaE8ynKvpC7RXZpJ9Nxfhd
apiServer:
port: "8080"
nodes:
- peerId: 12D3KooWMHuhZgK2skkLrvL51QQTXaXQKYy2QqfvPNBFnzR2ubA1
address: 127.0.0.1:4430
signingKey: 3id6ddLcoNoe9rDgGM88ET8T6TnvHm5GFqFdN6kBzn7Q8d6VUGgjeT59CNWFiaofdeRnHBvX2A5ZacMXvfwaYEFuCbug
encryptionKey: JgG4CcCbae1qEpe7mKpBzsHjZhXUmDSNVNX2B1gxFZsJyMX4V6kBQUott9zRWyeXaW1ZmpzuxDXnwSQpAnNurhXyGa9iQaAPqzY9A9VWBPD33Yy1eW7TRuVemzToh8jJQKQKnZNbF8ucTWV9qahusKzyvN8uyhrqoW2tAPfA9S3E3ognCuqbLSW6yjE2rBKayvyS1BVwzjSd6FZK4DDyjfU3pbEVjut3wytGEAn9af6sNMmyCnf2MX5vLovWs9rU8av61wD4z7HTsXyGFx4K75N4Go249Hpe9SKAT6HxhRc3yvj63krPLiQV5yMuH2UeMUXBDekUQyNmBEdn9wrur7mLqB67Bc6tcc2PP8XApBCdWJHvHjN4FktSpaG5vbCqoZbLD1oCbk36q2x9s6XM8pydVqD1J9P3nTbfgMb5pJCTFjNtgKeuKv6wjfJeA9jF1VhcJQisfsahgv9MvZ9M8FJpZTq1zKUhYDCRnZxUkraoMS5yNNVdDzaUckKEDthqik7BMWCWT79vq7uVgMwEvGwGi76gtoMg1159bbPMLZ4bdPVfhH2S9QjPrzQfwZSrzB2YeVPjWpaXDeLDity5H8n1NK2oniAQR6gE71n81neSptsuhV6o6QpQ89AU8y57XmEsou4VEryn8vUxBHhULLxrLNUouxyWamCeFiDjk5cSN6koQsf9BYKSNTPFTrwjTKForDokMhcPdMtFktKwjv7u9UEGcY4MKvNzZZkc77gHiP8bqVtdNNoLpTFUC5SZ9i7bKdHvK12HpSy7yzzPeMXJ9UwhLxkok1g81ngTbN1yxRhvYXyHZFtguCR9kvGojDjka91MTBtk551qDw9eCn2xZT9U8jqzBCjdpvSg3mRWKMPnYAGB7m7u1ye165wyGFvzcHAx3vtXjxAqLUeKYZCjv2m6V9D2Y4qH1TQNddWqH14T1JVMis971UCH9Ddpj6a3387oUnufD1P6HZN2ieJCvptrmbGVvxJYYSvmVf1dkwbtqurDRNWD7TJ7gf6iqSP549C9bxP4GpLt3ygjHmMtcuUzstBuztvunJUnQhfnJxqU6LjRdsFzm53wGWgXNxab7ZvQcPyLwsevn1b98FGPnVpS5iY4LjmqW4ugrC6HgrbsjrXiKzR1yZKhLQkCbLzPoaHb8iB5iBnCr7d4yf5CtfpFRqgoqMFdK5LNZYmDX4HzUKN6A7wC3gGiSRFTLcgGZeSMkB5Pa61CZBU7WCQgFxykycE9HRA7PiQa496GWDCV15teToCpFRsAa6jDmR1MGXPeLRqQgve49VXnQN5FL7c1VuEv5SWjeTuCnMB47DJKBaP7eKJNKgLwETALzSCMF3nRiRgeb15kfoS4BbrJ5yupjrvwmbmvNg1AYFFS5sYNWft7K8v87wQvBakRtGP71Kp8NX77XFtu6xdB7sR6jpfC6qJPyB9akWNXgCrWy9kE4ih42gwAZdUugNZ9YtEsgRM3pwb6qJhkAPyEJtrxrja859PCAgqPSQiPQN33PaMkgQ6HJknu8CrjKRiXAycZ16KLUkHV64TNhEjPTcX1a7rqpD131AYMWX8d7CCdc9Ys7RUb6BwguuNSh8rJK3x4AkMDSUsaE8ynKvpC7RXZpJ9Nxfhd
- peerId: 12D3KooWT3c7Y5zvWhhjSxd5Ve3GKZi6WCsG6JHxcxgXixRFdBbw
address: 127.0.0.1:4432
signingKey: 3iiLPj6wMUQpPwTBNZcUgkbXub1jumg4AEV9LfMyFHZVc84GLyAjVbVvH6EAGhcNrxRxL82aW4BimhDZCpLsRCqx5vwj
encryptionKey: JgG4CcCbae1qEpe7mKXzp7m5hNc56SSyZd9DwUaEStKJrq7RToAC2Vgd3i6hKRwa58zCWeN6Wjc3o6qrdKPEPRvcyEPysamajVo5mdQiUgWAmr97pGEsyjuRjQoC2GY2LvLiEQxEgwFgJxKGMHMiaWMtDfxCDUaDEm4bu5RdMhqRZekAWho6c3WoEeruSr14iX1TrocFNfBkBY7CjEw8kcywXCTNgtvhb2Qiwgj5AxEF4wyw4bzaNA9ctXb1hoHPFVMu6C51pkFY7jUD9zwyH3ukgnAewkGAcPNbKmaTAtMosKRVaAN97mAwXh2VRt1hWmRvVk7r76EjnVKhD4vbsKZc56RVcHTVWRVdhU7FGyPsiE5rSQAz1JQGYzxnZpX7EG77CyrmUGyfueVfRHhwY2oq8A4uQCRaQxSaJHYLowjXSxh8DQ2V6MTqyzti32C27utBYdHzLVCJSGkmdzGwrFcHqsq7nLDxmvJVErPvyReixEe8kFmqopJ3e6LLm8WdYw9K6JYBjXnEfwPzm7Von9sf3dcaGDUHYfttMyeke7fAXJkvPRje69hYVyzdQGAauuojzGkkvQWCSMK1KCMNMznRaPDCNvofrQhYrub24WhmwpKhorufdfW8Cb4T6reBDCtaWVsbuinjtL6F6Sui5aYHJFLJ6e4pPewr1P4EuZYRbMBZwN5KvDLhTGLBuBnaTqUUdF6bj2U22NoRYMogiHiftqKqiexKNDXX1Zg9RQEvxgjuVo6SBW42mVEA8agrLhruRqCmiduJxVrfqLNGeYXHXrcmMEgW7uosJbPXvTcfRvdFWS1ov7oSALvj6vhDQ28Yi9D2ETNdNsfVWAFQuwvPpW7CHQGXTitprVbqH8JYxNZuGygcLmr5efbB22Vzu4ntd1HoraQpG12qeDEUA7tXYUpoYyuSdWwKPjSAMtaQcCSfVrhKQHQuKJargrVrez8vjWuwLfvSucV7ZHe7gjqvYgULdE1ubRCRSd7DuLjEN2Vd6obzV2c3MRet7ZSf4Sp88WM5AuTyW7BjArBc4S3gUQ8rYaiZ8Tu7NCxkEzbFwWRaemZkwfvcsX3XxqjyF37tFSGkEqE5kuBvpZW72675LkDffj7kH1zA8yE6dVujJjWsNYVFJWndUtz5Vy2KCdZAbBgq19q4AtsxWPodU2N3yZXzFAFAzTrxS6V4P7Scpdau1avgRvHLcBQPunA37xaYMy8YMifJwtmRY25mnAQwZAk3eANk7tXwZd58SDnciLNvARJvwKzTQBXcshkwyy52SX8XmXDJsPnRLaHmiYBJ63Yzr5XpZuuAtxb9qrWG2NHCNxfomHokWacV1hjZPPd6ZxT1FuRozB6Qt2NLcyqY7bnTcQJb1jPUaTAGXXCR8WVmmmYo2fDQe8CdBmgyPvbzNTEJUyScBz4RdycB5PZap4SurJCWtHbuMyQbQUB6jJgURDstfXS5Akfe4oruNq9rnYcNtnsDJPtrhXHBqzDizmf1BDxR5FB2RCxzCgeAfg8WQ1Ug9PVAGTzob6ZqCrGXzWXEUniZnf1vjr7QhGKBYXEX9SWDoSMUpP4FreVDTnx15ijRZTV3p8xG5fE9e36TnugRVvTyq7XzmyPBjW2r66f1bior

View File

@ -0,0 +1,22 @@
anytype:
swarmKey: /key/swarm/psk/1.0.0/base16/209992e611c27d5dce8fbd2e7389f6b51da9bee980992ef60739460b536139ec
grpcServer:
listenAddrs:
- 127.0.0.1:4432
- 127.0.0.1:4433
tls: false
account:
peerId: 12D3KooWT3c7Y5zvWhhjSxd5Ve3GKZi6WCsG6JHxcxgXixRFdBbw
signingKey: 3iiLPj6wMUQpPwTBNZcUgkbXub1jumg4AEV9LfMyFHZVc84GLyAjVbVvH6EAGhcNrxRxL82aW4BimhDZCpLsRCqx5vwj
encryptionKey: JgG4CcCbae1qEpe7mKXzp7m5hNc56SSyZd9DwUaEStKJrq7RToAC2Vgd3i6hKRwa58zCWeN6Wjc3o6qrdKPEPRvcyEPysamajVo5mdQiUgWAmr97pGEsyjuRjQoC2GY2LvLiEQxEgwFgJxKGMHMiaWMtDfxCDUaDEm4bu5RdMhqRZekAWho6c3WoEeruSr14iX1TrocFNfBkBY7CjEw8kcywXCTNgtvhb2Qiwgj5AxEF4wyw4bzaNA9ctXb1hoHPFVMu6C51pkFY7jUD9zwyH3ukgnAewkGAcPNbKmaTAtMosKRVaAN97mAwXh2VRt1hWmRvVk7r76EjnVKhD4vbsKZc56RVcHTVWRVdhU7FGyPsiE5rSQAz1JQGYzxnZpX7EG77CyrmUGyfueVfRHhwY2oq8A4uQCRaQxSaJHYLowjXSxh8DQ2V6MTqyzti32C27utBYdHzLVCJSGkmdzGwrFcHqsq7nLDxmvJVErPvyReixEe8kFmqopJ3e6LLm8WdYw9K6JYBjXnEfwPzm7Von9sf3dcaGDUHYfttMyeke7fAXJkvPRje69hYVyzdQGAauuojzGkkvQWCSMK1KCMNMznRaPDCNvofrQhYrub24WhmwpKhorufdfW8Cb4T6reBDCtaWVsbuinjtL6F6Sui5aYHJFLJ6e4pPewr1P4EuZYRbMBZwN5KvDLhTGLBuBnaTqUUdF6bj2U22NoRYMogiHiftqKqiexKNDXX1Zg9RQEvxgjuVo6SBW42mVEA8agrLhruRqCmiduJxVrfqLNGeYXHXrcmMEgW7uosJbPXvTcfRvdFWS1ov7oSALvj6vhDQ28Yi9D2ETNdNsfVWAFQuwvPpW7CHQGXTitprVbqH8JYxNZuGygcLmr5efbB22Vzu4ntd1HoraQpG12qeDEUA7tXYUpoYyuSdWwKPjSAMtaQcCSfVrhKQHQuKJargrVrez8vjWuwLfvSucV7ZHe7gjqvYgULdE1ubRCRSd7DuLjEN2Vd6obzV2c3MRet7ZSf4Sp88WM5AuTyW7BjArBc4S3gUQ8rYaiZ8Tu7NCxkEzbFwWRaemZkwfvcsX3XxqjyF37tFSGkEqE5kuBvpZW72675LkDffj7kH1zA8yE6dVujJjWsNYVFJWndUtz5Vy2KCdZAbBgq19q4AtsxWPodU2N3yZXzFAFAzTrxS6V4P7Scpdau1avgRvHLcBQPunA37xaYMy8YMifJwtmRY25mnAQwZAk3eANk7tXwZd58SDnciLNvARJvwKzTQBXcshkwyy52SX8XmXDJsPnRLaHmiYBJ63Yzr5XpZuuAtxb9qrWG2NHCNxfomHokWacV1hjZPPd6ZxT1FuRozB6Qt2NLcyqY7bnTcQJb1jPUaTAGXXCR8WVmmmYo2fDQe8CdBmgyPvbzNTEJUyScBz4RdycB5PZap4SurJCWtHbuMyQbQUB6jJgURDstfXS5Akfe4oruNq9rnYcNtnsDJPtrhXHBqzDizmf1BDxR5FB2RCxzCgeAfg8WQ1Ug9PVAGTzob6ZqCrGXzWXEUniZnf1vjr7QhGKBYXEX9SWDoSMUpP4FreVDTnx15ijRZTV3p8xG5fE9e36TnugRVvTyq7XzmyPBjW2r66f1bior
apiServer:
port: "8081"
nodes:
- peerId: 12D3KooWMHuhZgK2skkLrvL51QQTXaXQKYy2QqfvPNBFnzR2ubA1
address: 127.0.0.1:4430
signingKey: 3id6ddLcoNoe9rDgGM88ET8T6TnvHm5GFqFdN6kBzn7Q8d6VUGgjeT59CNWFiaofdeRnHBvX2A5ZacMXvfwaYEFuCbug
encryptionKey: JgG4CcCbae1qEpe7mKpBzsHjZhXUmDSNVNX2B1gxFZsJyMX4V6kBQUott9zRWyeXaW1ZmpzuxDXnwSQpAnNurhXyGa9iQaAPqzY9A9VWBPD33Yy1eW7TRuVemzToh8jJQKQKnZNbF8ucTWV9qahusKzyvN8uyhrqoW2tAPfA9S3E3ognCuqbLSW6yjE2rBKayvyS1BVwzjSd6FZK4DDyjfU3pbEVjut3wytGEAn9af6sNMmyCnf2MX5vLovWs9rU8av61wD4z7HTsXyGFx4K75N4Go249Hpe9SKAT6HxhRc3yvj63krPLiQV5yMuH2UeMUXBDekUQyNmBEdn9wrur7mLqB67Bc6tcc2PP8XApBCdWJHvHjN4FktSpaG5vbCqoZbLD1oCbk36q2x9s6XM8pydVqD1J9P3nTbfgMb5pJCTFjNtgKeuKv6wjfJeA9jF1VhcJQisfsahgv9MvZ9M8FJpZTq1zKUhYDCRnZxUkraoMS5yNNVdDzaUckKEDthqik7BMWCWT79vq7uVgMwEvGwGi76gtoMg1159bbPMLZ4bdPVfhH2S9QjPrzQfwZSrzB2YeVPjWpaXDeLDity5H8n1NK2oniAQR6gE71n81neSptsuhV6o6QpQ89AU8y57XmEsou4VEryn8vUxBHhULLxrLNUouxyWamCeFiDjk5cSN6koQsf9BYKSNTPFTrwjTKForDokMhcPdMtFktKwjv7u9UEGcY4MKvNzZZkc77gHiP8bqVtdNNoLpTFUC5SZ9i7bKdHvK12HpSy7yzzPeMXJ9UwhLxkok1g81ngTbN1yxRhvYXyHZFtguCR9kvGojDjka91MTBtk551qDw9eCn2xZT9U8jqzBCjdpvSg3mRWKMPnYAGB7m7u1ye165wyGFvzcHAx3vtXjxAqLUeKYZCjv2m6V9D2Y4qH1TQNddWqH14T1JVMis971UCH9Ddpj6a3387oUnufD1P6HZN2ieJCvptrmbGVvxJYYSvmVf1dkwbtqurDRNWD7TJ7gf6iqSP549C9bxP4GpLt3ygjHmMtcuUzstBuztvunJUnQhfnJxqU6LjRdsFzm53wGWgXNxab7ZvQcPyLwsevn1b98FGPnVpS5iY4LjmqW4ugrC6HgrbsjrXiKzR1yZKhLQkCbLzPoaHb8iB5iBnCr7d4yf5CtfpFRqgoqMFdK5LNZYmDX4HzUKN6A7wC3gGiSRFTLcgGZeSMkB5Pa61CZBU7WCQgFxykycE9HRA7PiQa496GWDCV15teToCpFRsAa6jDmR1MGXPeLRqQgve49VXnQN5FL7c1VuEv5SWjeTuCnMB47DJKBaP7eKJNKgLwETALzSCMF3nRiRgeb15kfoS4BbrJ5yupjrvwmbmvNg1AYFFS5sYNWft7K8v87wQvBakRtGP71Kp8NX77XFtu6xdB7sR6jpfC6qJPyB9akWNXgCrWy9kE4ih42gwAZdUugNZ9YtEsgRM3pwb6qJhkAPyEJtrxrja859PCAgqPSQiPQN33PaMkgQ6HJknu8CrjKRiXAycZ16KLUkHV64TNhEjPTcX1a7rqpD131AYMWX8d7CCdc9Ys7RUb6BwguuNSh8rJK3x4AkMDSUsaE8ynKvpC7RXZpJ9Nxfhd
- peerId: 12D3KooWT3c7Y5zvWhhjSxd5Ve3GKZi6WCsG6JHxcxgXixRFdBbw
address: 127.0.0.1:4432
signingKey: 3iiLPj6wMUQpPwTBNZcUgkbXub1jumg4AEV9LfMyFHZVc84GLyAjVbVvH6EAGhcNrxRxL82aW4BimhDZCpLsRCqx5vwj
encryptionKey: JgG4CcCbae1qEpe7mKXzp7m5hNc56SSyZd9DwUaEStKJrq7RToAC2Vgd3i6hKRwa58zCWeN6Wjc3o6qrdKPEPRvcyEPysamajVo5mdQiUgWAmr97pGEsyjuRjQoC2GY2LvLiEQxEgwFgJxKGMHMiaWMtDfxCDUaDEm4bu5RdMhqRZekAWho6c3WoEeruSr14iX1TrocFNfBkBY7CjEw8kcywXCTNgtvhb2Qiwgj5AxEF4wyw4bzaNA9ctXb1hoHPFVMu6C51pkFY7jUD9zwyH3ukgnAewkGAcPNbKmaTAtMosKRVaAN97mAwXh2VRt1hWmRvVk7r76EjnVKhD4vbsKZc56RVcHTVWRVdhU7FGyPsiE5rSQAz1JQGYzxnZpX7EG77CyrmUGyfueVfRHhwY2oq8A4uQCRaQxSaJHYLowjXSxh8DQ2V6MTqyzti32C27utBYdHzLVCJSGkmdzGwrFcHqsq7nLDxmvJVErPvyReixEe8kFmqopJ3e6LLm8WdYw9K6JYBjXnEfwPzm7Von9sf3dcaGDUHYfttMyeke7fAXJkvPRje69hYVyzdQGAauuojzGkkvQWCSMK1KCMNMznRaPDCNvofrQhYrub24WhmwpKhorufdfW8Cb4T6reBDCtaWVsbuinjtL6F6Sui5aYHJFLJ6e4pPewr1P4EuZYRbMBZwN5KvDLhTGLBuBnaTqUUdF6bj2U22NoRYMogiHiftqKqiexKNDXX1Zg9RQEvxgjuVo6SBW42mVEA8agrLhruRqCmiduJxVrfqLNGeYXHXrcmMEgW7uosJbPXvTcfRvdFWS1ov7oSALvj6vhDQ28Yi9D2ETNdNsfVWAFQuwvPpW7CHQGXTitprVbqH8JYxNZuGygcLmr5efbB22Vzu4ntd1HoraQpG12qeDEUA7tXYUpoYyuSdWwKPjSAMtaQcCSfVrhKQHQuKJargrVrez8vjWuwLfvSucV7ZHe7gjqvYgULdE1ubRCRSd7DuLjEN2Vd6obzV2c3MRet7ZSf4Sp88WM5AuTyW7BjArBc4S3gUQ8rYaiZ8Tu7NCxkEzbFwWRaemZkwfvcsX3XxqjyF37tFSGkEqE5kuBvpZW72675LkDffj7kH1zA8yE6dVujJjWsNYVFJWndUtz5Vy2KCdZAbBgq19q4AtsxWPodU2N3yZXzFAFAzTrxS6V4P7Scpdau1avgRvHLcBQPunA37xaYMy8YMifJwtmRY25mnAQwZAk3eANk7tXwZd58SDnciLNvARJvwKzTQBXcshkwyy52SX8XmXDJsPnRLaHmiYBJ63Yzr5XpZuuAtxb9qrWG2NHCNxfomHokWacV1hjZPPd6ZxT1FuRozB6Qt2NLcyqY7bnTcQJb1jPUaTAGXXCR8WVmmmYo2fDQe8CdBmgyPvbzNTEJUyScBz4RdycB5PZap4SurJCWtHbuMyQbQUB6jJgURDstfXS5Akfe4oruNq9rnYcNtnsDJPtrhXHBqzDizmf1BDxR5FB2RCxzCgeAfg8WQ1Ug9PVAGTzob6ZqCrGXzWXEUniZnf1vjr7QhGKBYXEX9SWDoSMUpP4FreVDTnx15ijRZTV3p8xG5fE9e36TnugRVvTyq7XzmyPBjW2r66f1bior

29
go.mod
View File

@ -4,34 +4,51 @@ go 1.18
require ( require (
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab
github.com/cheggaaa/mb v1.0.3
github.com/goccy/go-graphviz v0.0.9 github.com/goccy/go-graphviz v0.0.9
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/ipfs/go-cid v0.0.7 github.com/ipfs/go-cid v0.1.0
github.com/libp2p/go-libp2p v0.20.3
github.com/libp2p/go-libp2p-core v0.16.1
github.com/mr-tron/base58 v1.2.0 github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multibase v0.0.3 github.com/multiformats/go-multibase v0.0.3
github.com/multiformats/go-multihash v0.0.15 github.com/multiformats/go-multihash v0.1.0
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
go.uber.org/zap v1.21.0 go.uber.org/zap v1.21.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
storj.io/drpc v0.0.32
) )
require ( require (
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/fogleman/gg v1.3.0 // indirect github.com/fogleman/gg v1.3.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/klauspost/cpuid/v2 v2.0.4 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
github.com/libp2p/go-openssl v0.0.7 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect github.com/minio/sha256-simd v1.0.0 // indirect
github.com/multiformats/go-base32 v0.0.3 // indirect github.com/multiformats/go-base32 v0.0.3 // indirect
github.com/multiformats/go-base36 v0.1.0 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multiaddr v0.5.0 // indirect
github.com/multiformats/go-multicodec v0.4.1 // indirect
github.com/multiformats/go-varint v0.0.6 // indirect github.com/multiformats/go-varint v0.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/zeebo/errs v1.2.2 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/blake3 v1.1.6 // indirect
) )

61
go.sum
View File

@ -1,12 +1,24 @@
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab h1:+cdNqtOJWjvepyhxy23G7z7vmpYCoC65AP0nqi1f53s= github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab h1:+cdNqtOJWjvepyhxy23G7z7vmpYCoC65AP0nqi1f53s=
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/cheggaaa/mb v1.0.3 h1:03ksWum+6kHclB+kjwKMaBtgl5gtNYUwNpxsHQciKe8=
github.com/cheggaaa/mb v1.0.3/go.mod h1:NUl0GBtFLlfg2o6iZwxzcG7Lslc2wV/ADTFbLXtVPE4=
github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA= github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA=
github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI= github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/goccy/go-graphviz v0.0.9 h1:s/FMMJ1Joj6La3S5ApO3Jk2cwM4LpXECC2muFx3IPQQ= github.com/goccy/go-graphviz v0.0.9 h1:s/FMMJ1Joj6La3S5ApO3Jk2cwM4LpXECC2muFx3IPQQ=
@ -15,18 +27,28 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0=
github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
github.com/libp2p/go-libp2p v0.20.3 h1:tjjDNfp7FqdI/7v1rXtB/BtELaPlAThL2uzlj18kcrw=
github.com/libp2p/go-libp2p v0.20.3/go.mod h1:I+vndVanE/p/SjFbnA+BEmmfAUEpWxrdXZeyQ1Dus5c=
github.com/libp2p/go-libp2p-core v0.16.1 h1:bWoiEBqVkpJ13hbv/f69tHODp86t6mvc4fBN4DkK73M=
github.com/libp2p/go-libp2p-core v0.16.1/go.mod h1:O3i/7y+LqUb0N+qhzXjBjjpchgptWAVMG1Voegk7b4c=
github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw=
github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
@ -40,11 +62,17 @@ github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4=
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM=
github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug=
github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk=
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4=
github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA=
github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
@ -55,6 +83,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -63,6 +94,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@ -79,8 +113,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg= golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@ -100,13 +135,15 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -125,10 +162,16 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c=
lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
storj.io/drpc v0.0.32 h1:5p5ZwsK/VOgapaCu+oxaPVwO6UwIs+iwdMiD50+R4PI=
storj.io/drpc v0.0.32/go.mod h1:6rcOyR/QQkSTX/9L5ZGtlZaE2PtXTTZl8d+ulSeeYEg=

View File

@ -50,7 +50,67 @@ func (x ACLChangeUserPermissions) String() string {
} }
func (ACLChangeUserPermissions) EnumDescriptor() ([]byte, []int) { func (ACLChangeUserPermissions) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 0} return fileDescriptor_37a022c841a51877, []int{1, 0}
}
type RawChange struct {
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
Id string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
}
func (m *RawChange) Reset() { *m = RawChange{} }
func (m *RawChange) String() string { return proto.CompactTextString(m) }
func (*RawChange) ProtoMessage() {}
func (*RawChange) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0}
}
func (m *RawChange) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *RawChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_RawChange.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *RawChange) XXX_Merge(src proto.Message) {
xxx_messageInfo_RawChange.Merge(m, src)
}
func (m *RawChange) XXX_Size() int {
return m.Size()
}
func (m *RawChange) XXX_DiscardUnknown() {
xxx_messageInfo_RawChange.DiscardUnknown(m)
}
var xxx_messageInfo_RawChange proto.InternalMessageInfo
func (m *RawChange) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func (m *RawChange) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *RawChange) GetId() string {
if m != nil {
return m.Id
}
return ""
} }
// the element of change tree used to store and internal apply smartBlock history // the element of change tree used to store and internal apply smartBlock history
@ -70,7 +130,7 @@ func (m *ACLChange) Reset() { *m = ACLChange{} }
func (m *ACLChange) String() string { return proto.CompactTextString(m) } func (m *ACLChange) String() string { return proto.CompactTextString(m) }
func (*ACLChange) ProtoMessage() {} func (*ACLChange) ProtoMessage() {}
func (*ACLChange) Descriptor() ([]byte, []int) { func (*ACLChange) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0} return fileDescriptor_37a022c841a51877, []int{1}
} }
func (m *ACLChange) XXX_Unmarshal(b []byte) error { func (m *ACLChange) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -170,7 +230,7 @@ func (m *ACLChangeACLContentValue) Reset() { *m = ACLChangeACLContentVal
func (m *ACLChangeACLContentValue) String() string { return proto.CompactTextString(m) } func (m *ACLChangeACLContentValue) String() string { return proto.CompactTextString(m) }
func (*ACLChangeACLContentValue) ProtoMessage() {} func (*ACLChangeACLContentValue) ProtoMessage() {}
func (*ACLChangeACLContentValue) Descriptor() ([]byte, []int) { func (*ACLChangeACLContentValue) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 0} return fileDescriptor_37a022c841a51877, []int{1, 0}
} }
func (m *ACLChangeACLContentValue) XXX_Unmarshal(b []byte) error { func (m *ACLChangeACLContentValue) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -301,7 +361,7 @@ func (m *ACLChangeACLData) Reset() { *m = ACLChangeACLData{} }
func (m *ACLChangeACLData) String() string { return proto.CompactTextString(m) } func (m *ACLChangeACLData) String() string { return proto.CompactTextString(m) }
func (*ACLChangeACLData) ProtoMessage() {} func (*ACLChangeACLData) ProtoMessage() {}
func (*ACLChangeACLData) Descriptor() ([]byte, []int) { func (*ACLChangeACLData) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 1} return fileDescriptor_37a022c841a51877, []int{1, 1}
} }
func (m *ACLChangeACLData) XXX_Unmarshal(b []byte) error { func (m *ACLChangeACLData) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -353,7 +413,7 @@ func (m *ACLChangeACLSnapshot) Reset() { *m = ACLChangeACLSnapshot{} }
func (m *ACLChangeACLSnapshot) String() string { return proto.CompactTextString(m) } func (m *ACLChangeACLSnapshot) String() string { return proto.CompactTextString(m) }
func (*ACLChangeACLSnapshot) ProtoMessage() {} func (*ACLChangeACLSnapshot) ProtoMessage() {}
func (*ACLChangeACLSnapshot) Descriptor() ([]byte, []int) { func (*ACLChangeACLSnapshot) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 2} return fileDescriptor_37a022c841a51877, []int{1, 2}
} }
func (m *ACLChangeACLSnapshot) XXX_Unmarshal(b []byte) error { func (m *ACLChangeACLSnapshot) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -399,7 +459,7 @@ func (m *ACLChangeACLState) Reset() { *m = ACLChangeACLState{} }
func (m *ACLChangeACLState) String() string { return proto.CompactTextString(m) } func (m *ACLChangeACLState) String() string { return proto.CompactTextString(m) }
func (*ACLChangeACLState) ProtoMessage() {} func (*ACLChangeACLState) ProtoMessage() {}
func (*ACLChangeACLState) Descriptor() ([]byte, []int) { func (*ACLChangeACLState) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 3} return fileDescriptor_37a022c841a51877, []int{1, 3}
} }
func (m *ACLChangeACLState) XXX_Unmarshal(b []byte) error { func (m *ACLChangeACLState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -453,7 +513,7 @@ type ACLChangeUserState struct {
Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"` EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"`
EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"`
Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=anytype.ACLChangeUserPermissions" json:"permissions,omitempty"` Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=acl.ACLChangeUserPermissions" json:"permissions,omitempty"`
IsConfirmed bool `protobuf:"varint,5,opt,name=IsConfirmed,proto3" json:"IsConfirmed,omitempty"` IsConfirmed bool `protobuf:"varint,5,opt,name=IsConfirmed,proto3" json:"IsConfirmed,omitempty"`
} }
@ -461,7 +521,7 @@ func (m *ACLChangeUserState) Reset() { *m = ACLChangeUserState{} }
func (m *ACLChangeUserState) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserState) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserState) ProtoMessage() {} func (*ACLChangeUserState) ProtoMessage() {}
func (*ACLChangeUserState) Descriptor() ([]byte, []int) { func (*ACLChangeUserState) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 4} return fileDescriptor_37a022c841a51877, []int{1, 4}
} }
func (m *ACLChangeUserState) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -530,14 +590,14 @@ type ACLChangeUserAdd struct {
Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"` EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"`
EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"`
Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=anytype.ACLChangeUserPermissions" json:"permissions,omitempty"` Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=acl.ACLChangeUserPermissions" json:"permissions,omitempty"`
} }
func (m *ACLChangeUserAdd) Reset() { *m = ACLChangeUserAdd{} } func (m *ACLChangeUserAdd) Reset() { *m = ACLChangeUserAdd{} }
func (m *ACLChangeUserAdd) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserAdd) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserAdd) ProtoMessage() {} func (*ACLChangeUserAdd) ProtoMessage() {}
func (*ACLChangeUserAdd) Descriptor() ([]byte, []int) { func (*ACLChangeUserAdd) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 5} return fileDescriptor_37a022c841a51877, []int{1, 5}
} }
func (m *ACLChangeUserAdd) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserAdd) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -604,7 +664,7 @@ func (m *ACLChangeUserConfirm) Reset() { *m = ACLChangeUserConfirm{} }
func (m *ACLChangeUserConfirm) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserConfirm) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserConfirm) ProtoMessage() {} func (*ACLChangeUserConfirm) ProtoMessage() {}
func (*ACLChangeUserConfirm) Descriptor() ([]byte, []int) { func (*ACLChangeUserConfirm) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 6} return fileDescriptor_37a022c841a51877, []int{1, 6}
} }
func (m *ACLChangeUserConfirm) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserConfirm) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -651,7 +711,7 @@ type ACLChangeUserInvite struct {
AcceptPublicKey []byte `protobuf:"bytes,1,opt,name=acceptPublicKey,proto3" json:"acceptPublicKey,omitempty"` AcceptPublicKey []byte `protobuf:"bytes,1,opt,name=acceptPublicKey,proto3" json:"acceptPublicKey,omitempty"`
EncryptPublicKey []byte `protobuf:"bytes,2,opt,name=encryptPublicKey,proto3" json:"encryptPublicKey,omitempty"` EncryptPublicKey []byte `protobuf:"bytes,2,opt,name=encryptPublicKey,proto3" json:"encryptPublicKey,omitempty"`
EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"`
Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=anytype.ACLChangeUserPermissions" json:"permissions,omitempty"` Permissions ACLChangeUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=acl.ACLChangeUserPermissions" json:"permissions,omitempty"`
InviteId string `protobuf:"bytes,5,opt,name=InviteId,proto3" json:"InviteId,omitempty"` InviteId string `protobuf:"bytes,5,opt,name=InviteId,proto3" json:"InviteId,omitempty"`
} }
@ -659,7 +719,7 @@ func (m *ACLChangeUserInvite) Reset() { *m = ACLChangeUserInvite{} }
func (m *ACLChangeUserInvite) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserInvite) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserInvite) ProtoMessage() {} func (*ACLChangeUserInvite) ProtoMessage() {}
func (*ACLChangeUserInvite) Descriptor() ([]byte, []int) { func (*ACLChangeUserInvite) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 7} return fileDescriptor_37a022c841a51877, []int{1, 7}
} }
func (m *ACLChangeUserInvite) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserInvite) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -735,7 +795,7 @@ func (m *ACLChangeUserJoin) Reset() { *m = ACLChangeUserJoin{} }
func (m *ACLChangeUserJoin) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserJoin) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserJoin) ProtoMessage() {} func (*ACLChangeUserJoin) ProtoMessage() {}
func (*ACLChangeUserJoin) Descriptor() ([]byte, []int) { func (*ACLChangeUserJoin) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 8} return fileDescriptor_37a022c841a51877, []int{1, 8}
} }
func (m *ACLChangeUserJoin) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserJoin) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -808,7 +868,7 @@ func (m *ACLChangeUserRemove) Reset() { *m = ACLChangeUserRemove{} }
func (m *ACLChangeUserRemove) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserRemove) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserRemove) ProtoMessage() {} func (*ACLChangeUserRemove) ProtoMessage() {}
func (*ACLChangeUserRemove) Descriptor() ([]byte, []int) { func (*ACLChangeUserRemove) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 9} return fileDescriptor_37a022c841a51877, []int{1, 9}
} }
func (m *ACLChangeUserRemove) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserRemove) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -861,7 +921,7 @@ func (m *ACLChangeReadKeyReplace) Reset() { *m = ACLChangeReadKeyReplace
func (m *ACLChangeReadKeyReplace) String() string { return proto.CompactTextString(m) } func (m *ACLChangeReadKeyReplace) String() string { return proto.CompactTextString(m) }
func (*ACLChangeReadKeyReplace) ProtoMessage() {} func (*ACLChangeReadKeyReplace) ProtoMessage() {}
func (*ACLChangeReadKeyReplace) Descriptor() ([]byte, []int) { func (*ACLChangeReadKeyReplace) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 10} return fileDescriptor_37a022c841a51877, []int{1, 10}
} }
func (m *ACLChangeReadKeyReplace) XXX_Unmarshal(b []byte) error { func (m *ACLChangeReadKeyReplace) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -913,14 +973,14 @@ func (m *ACLChangeReadKeyReplace) GetEncryptedReadKey() []byte {
type ACLChangeUserPermissionChange struct { type ACLChangeUserPermissionChange struct {
Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` Identity string `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
Permissions ACLChangeUserPermissions `protobuf:"varint,2,opt,name=permissions,proto3,enum=anytype.ACLChangeUserPermissions" json:"permissions,omitempty"` Permissions ACLChangeUserPermissions `protobuf:"varint,2,opt,name=permissions,proto3,enum=acl.ACLChangeUserPermissions" json:"permissions,omitempty"`
} }
func (m *ACLChangeUserPermissionChange) Reset() { *m = ACLChangeUserPermissionChange{} } func (m *ACLChangeUserPermissionChange) Reset() { *m = ACLChangeUserPermissionChange{} }
func (m *ACLChangeUserPermissionChange) String() string { return proto.CompactTextString(m) } func (m *ACLChangeUserPermissionChange) String() string { return proto.CompactTextString(m) }
func (*ACLChangeUserPermissionChange) ProtoMessage() {} func (*ACLChangeUserPermissionChange) ProtoMessage() {}
func (*ACLChangeUserPermissionChange) Descriptor() ([]byte, []int) { func (*ACLChangeUserPermissionChange) Descriptor() ([]byte, []int) {
return fileDescriptor_37a022c841a51877, []int{0, 11} return fileDescriptor_37a022c841a51877, []int{1, 11}
} }
func (m *ACLChangeUserPermissionChange) XXX_Unmarshal(b []byte) error { func (m *ACLChangeUserPermissionChange) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -964,21 +1024,22 @@ func (m *ACLChangeUserPermissionChange) GetPermissions() ACLChangeUserPermission
} }
func init() { func init() {
proto.RegisterEnum("anytype.ACLChangeUserPermissions", ACLChangeUserPermissions_name, ACLChangeUserPermissions_value) proto.RegisterEnum("acl.ACLChangeUserPermissions", ACLChangeUserPermissions_name, ACLChangeUserPermissions_value)
proto.RegisterType((*ACLChange)(nil), "anytype.ACLChange") proto.RegisterType((*RawChange)(nil), "acl.RawChange")
proto.RegisterType((*ACLChangeACLContentValue)(nil), "anytype.ACLChange.ACLContentValue") proto.RegisterType((*ACLChange)(nil), "acl.ACLChange")
proto.RegisterType((*ACLChangeACLData)(nil), "anytype.ACLChange.ACLData") proto.RegisterType((*ACLChangeACLContentValue)(nil), "acl.ACLChange.ACLContentValue")
proto.RegisterType((*ACLChangeACLSnapshot)(nil), "anytype.ACLChange.ACLSnapshot") proto.RegisterType((*ACLChangeACLData)(nil), "acl.ACLChange.ACLData")
proto.RegisterType((*ACLChangeACLState)(nil), "anytype.ACLChange.ACLState") proto.RegisterType((*ACLChangeACLSnapshot)(nil), "acl.ACLChange.ACLSnapshot")
proto.RegisterMapType((map[string]*ACLChangeUserInvite)(nil), "anytype.ACLChange.ACLState.InvitesEntry") proto.RegisterType((*ACLChangeACLState)(nil), "acl.ACLChange.ACLState")
proto.RegisterType((*ACLChangeUserState)(nil), "anytype.ACLChange.UserState") proto.RegisterMapType((map[string]*ACLChangeUserInvite)(nil), "acl.ACLChange.ACLState.InvitesEntry")
proto.RegisterType((*ACLChangeUserAdd)(nil), "anytype.ACLChange.UserAdd") proto.RegisterType((*ACLChangeUserState)(nil), "acl.ACLChange.UserState")
proto.RegisterType((*ACLChangeUserConfirm)(nil), "anytype.ACLChange.UserConfirm") proto.RegisterType((*ACLChangeUserAdd)(nil), "acl.ACLChange.UserAdd")
proto.RegisterType((*ACLChangeUserInvite)(nil), "anytype.ACLChange.UserInvite") proto.RegisterType((*ACLChangeUserConfirm)(nil), "acl.ACLChange.UserConfirm")
proto.RegisterType((*ACLChangeUserJoin)(nil), "anytype.ACLChange.UserJoin") proto.RegisterType((*ACLChangeUserInvite)(nil), "acl.ACLChange.UserInvite")
proto.RegisterType((*ACLChangeUserRemove)(nil), "anytype.ACLChange.UserRemove") proto.RegisterType((*ACLChangeUserJoin)(nil), "acl.ACLChange.UserJoin")
proto.RegisterType((*ACLChangeReadKeyReplace)(nil), "anytype.ACLChange.ReadKeyReplace") proto.RegisterType((*ACLChangeUserRemove)(nil), "acl.ACLChange.UserRemove")
proto.RegisterType((*ACLChangeUserPermissionChange)(nil), "anytype.ACLChange.UserPermissionChange") proto.RegisterType((*ACLChangeReadKeyReplace)(nil), "acl.ACLChange.ReadKeyReplace")
proto.RegisterType((*ACLChangeUserPermissionChange)(nil), "acl.ACLChange.UserPermissionChange")
} }
func init() { func init() {
@ -986,65 +1047,111 @@ func init() {
} }
var fileDescriptor_37a022c841a51877 = []byte{ var fileDescriptor_37a022c841a51877 = []byte{
// 915 bytes of a gzipped FileDescriptorProto // 948 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0x4d, 0x6f, 0xe3, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0x4f, 0x6f, 0xe3, 0x44,
0x18, 0xf6, 0x24, 0x4d, 0x1d, 0xbf, 0x0e, 0x6d, 0x18, 0xf5, 0x60, 0x79, 0x8b, 0x09, 0x15, 0x82, 0x14, 0xf7, 0xc4, 0x4d, 0x1d, 0x3f, 0x87, 0x36, 0x0c, 0x2b, 0xd6, 0x58, 0x4b, 0x88, 0xca, 0x0a,
0x08, 0xa1, 0x2c, 0xca, 0x22, 0xbe, 0x84, 0x04, 0x4d, 0x17, 0x48, 0x28, 0x87, 0xd5, 0xac, 0x00, 0x45, 0x08, 0xa5, 0xab, 0xac, 0x90, 0x56, 0x80, 0x2a, 0xda, 0x82, 0x36, 0xa1, 0x1c, 0x56, 0x53,
0x81, 0xc4, 0x61, 0x6a, 0x0f, 0xad, 0xb5, 0x89, 0x6d, 0x79, 0x26, 0x15, 0xb9, 0xf0, 0x0f, 0x10, 0x2d, 0x08, 0x6e, 0x53, 0x7b, 0x68, 0xad, 0x75, 0x6c, 0xe3, 0x99, 0x14, 0xe5, 0x82, 0xc4, 0x89,
0xfc, 0x16, 0xae, 0x1c, 0xb8, 0xee, 0x71, 0x8f, 0x1c, 0x51, 0xfb, 0x0f, 0xf8, 0x05, 0x68, 0x3e, 0x2b, 0x67, 0xbe, 0x0a, 0x5f, 0x60, 0x8f, 0x7b, 0xe4, 0x06, 0x6a, 0xef, 0x5c, 0xf8, 0x02, 0x68,
0xec, 0x38, 0xa9, 0x1d, 0x24, 0xb4, 0x12, 0xe2, 0x10, 0x69, 0xe6, 0x99, 0xe7, 0x1d, 0xbf, 0x1f, 0xfe, 0xd8, 0x71, 0x12, 0x6f, 0x24, 0xa4, 0x15, 0x12, 0x87, 0x4a, 0x33, 0xbf, 0xf7, 0x7b, 0xd3,
0xcf, 0xfb, 0x4e, 0xe0, 0xad, 0xec, 0xc9, 0xe5, 0x7d, 0x1a, 0xce, 0xe5, 0x2f, 0xbc, 0xa2, 0xc9, 0xf7, 0xde, 0xef, 0xbd, 0x17, 0xc3, 0x83, 0xfc, 0xd9, 0xe5, 0x21, 0x0d, 0x13, 0xf9, 0x17, 0x5e,
0x25, 0xe3, 0x72, 0x99, 0x5d, 0xdc, 0xcf, 0xf2, 0x54, 0xa4, 0xbc, 0x82, 0x8f, 0x14, 0x82, 0x6d, 0xd1, 0xf4, 0x92, 0x71, 0x79, 0xcc, 0x2f, 0x0e, 0xf3, 0x22, 0x13, 0x19, 0xaf, 0xe1, 0x23, 0x85,
0x9a, 0xac, 0xc4, 0x2a, 0x63, 0x27, 0xbf, 0x1d, 0x81, 0x73, 0x7a, 0xf6, 0xc5, 0x99, 0x3a, 0xc5, 0x60, 0x9b, 0x86, 0xc9, 0xc1, 0x39, 0xb8, 0x84, 0xfe, 0x70, 0xaa, 0x0c, 0xd8, 0x07, 0x27, 0xa7,
0x03, 0x70, 0x45, 0xce, 0xd8, 0x94, 0xd1, 0x68, 0x16, 0x71, 0x0f, 0x0d, 0xda, 0x43, 0x87, 0x54, 0x8b, 0x24, 0xa3, 0x91, 0x8f, 0x06, 0x68, 0xd8, 0x25, 0xe5, 0x15, 0xdf, 0x03, 0x97, 0xc7, 0x97,
0x21, 0x1c, 0x00, 0xd0, 0x70, 0x5e, 0x10, 0x5a, 0x8a, 0x50, 0x41, 0xf0, 0x6b, 0x70, 0xc0, 0x13, 0x29, 0x15, 0xf3, 0x82, 0xf9, 0x2d, 0x65, 0x5b, 0x02, 0x78, 0x0f, 0x5a, 0x71, 0xe4, 0xdb, 0x03,
0x9a, 0xf1, 0xab, 0x54, 0x4c, 0x28, 0x67, 0xb3, 0xc8, 0x6b, 0x0f, 0xd0, 0xd0, 0x21, 0x5b, 0x28, 0x34, 0x74, 0x49, 0x2b, 0x8e, 0x0e, 0xfe, 0x7e, 0x03, 0xdc, 0xe3, 0xd3, 0x2f, 0xcd, 0xab, 0x03,
0x7e, 0x1b, 0x6c, 0x1a, 0xce, 0x1f, 0x52, 0x41, 0xbd, 0xbd, 0x01, 0x1a, 0xba, 0x63, 0x7f, 0x64, 0xf0, 0x44, 0xc1, 0xd8, 0x84, 0xd1, 0x68, 0x1a, 0x71, 0x1f, 0x0d, 0xec, 0xa1, 0x4b, 0xea, 0x10,
0x5c, 0x1a, 0x95, 0xee, 0xc8, 0x95, 0x64, 0x90, 0x82, 0x2a, 0xfd, 0x33, 0x71, 0x28, 0xcb, 0xce, 0xee, 0x03, 0xd0, 0x30, 0x29, 0x09, 0x2d, 0x45, 0xa8, 0x21, 0xf8, 0x3d, 0xd8, 0xe3, 0x29, 0xcd,
0x00, 0x0d, 0x7b, 0xa4, 0x0a, 0xe1, 0x11, 0xe0, 0x70, 0x99, 0xe7, 0x2c, 0x11, 0x84, 0xd1, 0xe8, 0xf9, 0x55, 0x26, 0x4e, 0x28, 0x67, 0xd3, 0xf2, 0x7f, 0xad, 0xa1, 0xf8, 0x01, 0x38, 0x34, 0x4c,
0x9c, 0xad, 0xa6, 0x94, 0x5f, 0x79, 0xfb, 0x03, 0x34, 0xdc, 0x23, 0x35, 0x27, 0xf8, 0x18, 0x1c, 0x3e, 0xa3, 0x82, 0xfa, 0x3b, 0x03, 0x34, 0xf4, 0xc6, 0x6f, 0x8e, 0x68, 0x98, 0x8c, 0xaa, 0x50,
0x11, 0x2f, 0x18, 0x17, 0x74, 0x91, 0x79, 0xf6, 0x00, 0x0d, 0xdb, 0x64, 0x0d, 0x60, 0x1f, 0xba, 0xe4, 0x49, 0x5a, 0x49, 0x49, 0x93, 0xb1, 0x99, 0xa2, 0x28, 0xaf, 0xb6, 0xca, 0xac, 0x0e, 0xe1,
0x71, 0xc4, 0x12, 0x11, 0x8b, 0x95, 0xd7, 0x55, 0x71, 0x94, 0x7b, 0xff, 0xd7, 0x36, 0x1c, 0x4a, 0x11, 0xe0, 0x70, 0x5e, 0x14, 0x2c, 0x15, 0x84, 0xd1, 0xe8, 0x8c, 0x2d, 0x26, 0x94, 0x5f, 0xf9,
0x57, 0xd3, 0x44, 0xb0, 0x44, 0x7c, 0x45, 0xe7, 0x4b, 0x86, 0xdf, 0x01, 0x7b, 0xc9, 0x59, 0x7e, 0xbb, 0x03, 0x34, 0xdc, 0x21, 0x0d, 0x16, 0x59, 0x29, 0x11, 0xcf, 0x18, 0x17, 0x74, 0x96, 0xfb,
0x1a, 0x45, 0x1e, 0x6a, 0x8c, 0xea, 0x4b, 0xcd, 0x98, 0x5a, 0xa4, 0x20, 0xe3, 0x8f, 0x00, 0xe4, 0xce, 0x00, 0x0d, 0x6d, 0xb2, 0x04, 0x70, 0x00, 0x9d, 0x38, 0x62, 0xa9, 0x88, 0xc5, 0xc2, 0xef,
0x92, 0xb0, 0x45, 0x7a, 0xcd, 0xbc, 0x96, 0x32, 0x7d, 0xa9, 0xc1, 0x54, 0x93, 0xa6, 0x16, 0xa9, 0xa8, 0x1c, 0xaa, 0x7b, 0xf0, 0xab, 0x0d, 0xfb, 0x32, 0xd4, 0x2c, 0x15, 0x2c, 0x15, 0x5f, 0xd1,
0x98, 0xe0, 0xef, 0xe0, 0x48, 0xee, 0x1e, 0xb1, 0x7c, 0x11, 0x73, 0x1e, 0xa7, 0x89, 0x36, 0x50, 0x64, 0xce, 0xf0, 0x18, 0x9c, 0x39, 0x67, 0xc5, 0x71, 0xa4, 0x15, 0xd9, 0xcc, 0xe8, 0xa9, 0xb6,
0xc9, 0x77, 0xc7, 0xaf, 0x37, 0x5c, 0xb5, 0x4d, 0x9f, 0x5a, 0xa4, 0xf6, 0x9a, 0xc2, 0xbf, 0x59, 0x4e, 0x2c, 0x52, 0x12, 0xf1, 0xc7, 0x00, 0xf2, 0x48, 0xd8, 0x2c, 0xbb, 0xd6, 0x62, 0x79, 0xe3,
0x72, 0x1d, 0x0b, 0x66, 0x0a, 0xd6, 0xe4, 0x9f, 0x26, 0x15, 0xfe, 0xe9, 0x1d, 0x7e, 0x1f, 0xba, 0xb7, 0x1a, 0xdc, 0x34, 0x61, 0x62, 0x91, 0x1a, 0x1d, 0x7f, 0x03, 0x77, 0xe4, 0xed, 0x09, 0x2b,
0x72, 0xf7, 0x79, 0x1a, 0x27, 0xaa, 0x6a, 0xee, 0xf8, 0x5e, 0x83, 0xb9, 0xa4, 0x4c, 0x2d, 0x52, 0x66, 0x31, 0xe7, 0x71, 0x96, 0x6a, 0x07, 0x55, 0x70, 0x6f, 0xfc, 0x6e, 0xc3, 0x33, 0xeb, 0xd4,
0xd2, 0xf1, 0x04, 0x5c, 0xb9, 0x3e, 0x4b, 0x93, 0xef, 0xe3, 0x7c, 0xa1, 0x4a, 0xe9, 0x8e, 0x83, 0x89, 0x45, 0x1a, 0x9f, 0x28, 0xe3, 0x9a, 0xa6, 0xd7, 0xb1, 0x60, 0x46, 0xa0, 0xa6, 0xb8, 0x34,
0x06, 0x6b, 0xc3, 0x9a, 0x5a, 0xa4, 0x6a, 0x34, 0xb1, 0xa1, 0x73, 0x2d, 0x0b, 0xe4, 0xff, 0x8c, 0xa1, 0x8c, 0x4b, 0xdf, 0xf0, 0x87, 0xd0, 0x91, 0xb7, 0x2f, 0xb2, 0x38, 0x55, 0x2a, 0x79, 0xe3,
0xc0, 0x36, 0xaa, 0xc2, 0x1f, 0x83, 0x4b, 0xc3, 0xf9, 0x63, 0xa3, 0x4b, 0x53, 0xb0, 0xa0, 0x5e, 0xbb, 0x0d, 0xae, 0xd2, 0x3c, 0xb1, 0x48, 0x45, 0xc5, 0x47, 0xe0, 0xc9, 0xf3, 0x69, 0x96, 0x7e,
0x86, 0x05, 0x8b, 0x54, 0x4d, 0xf0, 0x44, 0x35, 0x83, 0x51, 0x80, 0x6a, 0x06, 0x77, 0x7c, 0x52, 0x17, 0x17, 0x33, 0x25, 0x9b, 0x37, 0x0e, 0x1a, 0x3c, 0x0d, 0x63, 0x62, 0x91, 0xba, 0xc3, 0x89,
0x7f, 0x41, 0x55, 0x26, 0xa4, 0x62, 0xe5, 0x7f, 0x0a, 0x6e, 0xe5, 0x7e, 0xfc, 0x2e, 0x74, 0xe5, 0x03, 0xed, 0x6b, 0x29, 0x44, 0xf0, 0x33, 0x02, 0xc7, 0x74, 0x0f, 0xfe, 0x04, 0x3c, 0x1a, 0x26,
0x17, 0x04, 0x15, 0xcc, 0x78, 0x74, 0xaf, 0xc1, 0x23, 0x49, 0x21, 0x25, 0xd9, 0xff, 0xa9, 0x05, 0xe7, 0xa6, 0xf7, 0x8c, 0x30, 0xc1, 0x66, 0xab, 0x95, 0x0c, 0x52, 0xa7, 0xe3, 0x23, 0xd5, 0xec,
0xdd, 0x02, 0xc6, 0xaf, 0xc2, 0x0b, 0xf9, 0x5a, 0xe4, 0x4c, 0x77, 0xf2, 0x1e, 0xd9, 0x04, 0xf1, 0x46, 0x65, 0xd5, 0xec, 0xde, 0xb8, 0xbf, 0xe9, 0x5c, 0x6f, 0x03, 0x52, 0xf3, 0x08, 0x4e, 0xc0,
0x87, 0xba, 0xaa, 0xca, 0x84, 0x1b, 0xf7, 0x8f, 0x1b, 0x12, 0xab, 0x3f, 0x57, 0xe1, 0xe3, 0x09, 0xab, 0xbd, 0x8d, 0x1f, 0x42, 0x47, 0xbe, 0x2e, 0xa8, 0x60, 0x26, 0x92, 0xbb, 0x0d, 0x91, 0x48,
0xd8, 0xb1, 0x2a, 0x2e, 0xf7, 0xda, 0xca, 0x74, 0xb8, 0xc3, 0xd1, 0x91, 0xd6, 0x01, 0xff, 0x24, 0x33, 0xa9, 0x88, 0xc1, 0x4f, 0x2d, 0xe8, 0x94, 0x30, 0xbe, 0x0f, 0xaf, 0x15, 0xcb, 0x06, 0x66,
0x11, 0xf9, 0x8a, 0x14, 0x86, 0xfe, 0x37, 0xd0, 0xab, 0x1e, 0xe0, 0x3e, 0xb4, 0x9f, 0xb0, 0x95, 0x7a, 0x42, 0x77, 0xc8, 0x2a, 0x88, 0x1f, 0x69, 0xf5, 0x94, 0x0b, 0x37, 0x61, 0xfb, 0x0d, 0x85,
0x0a, 0xdc, 0x21, 0x72, 0x89, 0x1f, 0x98, 0xca, 0xfd, 0x43, 0x53, 0xe8, 0x5b, 0x88, 0xe6, 0x7e, 0xd4, 0xff, 0xaa, 0xc6, 0xc5, 0x47, 0xe0, 0xc4, 0x4a, 0x44, 0xee, 0xdb, 0xca, 0xed, 0xfe, 0x4b,
0xd0, 0x7a, 0x0f, 0xf9, 0xb7, 0x08, 0x9c, 0xd2, 0xf1, 0x8d, 0x46, 0x46, 0x9b, 0x8d, 0x2c, 0x93, 0x02, 0x1c, 0x69, 0xad, 0xf9, 0xe7, 0xa9, 0x28, 0x16, 0xa4, 0x74, 0x0a, 0x9e, 0x42, 0xb7, 0x6e,
0xc5, 0x92, 0x30, 0x5f, 0x65, 0x22, 0x4e, 0x93, 0x73, 0xb6, 0x52, 0x9f, 0xea, 0x91, 0x4d, 0x10, 0xc0, 0x3d, 0xb0, 0x9f, 0xb1, 0x85, 0x4a, 0xd6, 0x25, 0xf2, 0x88, 0x0f, 0x8d, 0x4a, 0x5b, 0x9a,
0xbf, 0x09, 0x2f, 0x1a, 0x80, 0x45, 0x66, 0x80, 0xe8, 0xc0, 0x7b, 0xe4, 0xee, 0x01, 0x7e, 0x08, 0x5d, 0xbf, 0x40, 0x34, 0xef, 0xa3, 0xd6, 0x23, 0x14, 0xfc, 0x81, 0xc0, 0xad, 0x02, 0x5e, 0x19,
0x6e, 0x56, 0x36, 0x11, 0x57, 0x1d, 0x73, 0x50, 0x2b, 0x8d, 0xcd, 0x36, 0xe4, 0xa4, 0x6a, 0x26, 0x4c, 0xb4, 0x3a, 0x98, 0xb2, 0x40, 0x2c, 0x0d, 0x8b, 0x45, 0x2e, 0xe2, 0x2c, 0x3d, 0x63, 0x0b,
0xc7, 0xdd, 0x8c, 0x1b, 0x0d, 0xb3, 0x48, 0x35, 0x4e, 0x97, 0x54, 0x21, 0xff, 0x77, 0x04, 0xb6, 0xb3, 0x00, 0x57, 0x41, 0xfc, 0x01, 0xbc, 0x6e, 0x00, 0x16, 0x99, 0x85, 0xa0, 0x13, 0xee, 0x92,
0x99, 0x27, 0xff, 0xcf, 0x18, 0xfd, 0xcf, 0xc0, 0xad, 0x34, 0xee, 0xce, 0x20, 0x8e, 0xc1, 0x31, 0x4d, 0x03, 0xfe, 0x14, 0xbc, 0xbc, 0x1a, 0x10, 0xae, 0xa6, 0x61, 0x6f, 0xa3, 0x0d, 0x56, 0xc7,
0x03, 0x73, 0x16, 0xa9, 0x00, 0x1c, 0xb2, 0x06, 0xfc, 0xbf, 0x10, 0xc0, 0x5a, 0x0a, 0x78, 0x08, 0x8b, 0x93, 0xba, 0x8b, 0x5c, 0x5d, 0x53, 0x6e, 0xfa, 0x94, 0x45, 0x6a, 0x28, 0x3a, 0xa4, 0x0e,
0x87, 0x34, 0x0c, 0x59, 0x26, 0x1e, 0x2d, 0x2f, 0xe6, 0x71, 0x78, 0x6e, 0x64, 0xd5, 0x23, 0xdb, 0x05, 0xbf, 0x21, 0x70, 0xcc, 0x7e, 0xf8, 0xff, 0xe5, 0x17, 0x3c, 0x06, 0xaf, 0x36, 0x98, 0x5b,
0x30, 0x7e, 0x03, 0xfa, 0x26, 0xb8, 0x35, 0x55, 0xa7, 0xe7, 0x0e, 0xfe, 0x9f, 0xa8, 0xc0, 0x87, 0x13, 0xb8, 0x07, 0xae, 0x59, 0x7e, 0xd3, 0x48, 0x05, 0xef, 0x92, 0x25, 0x10, 0xfc, 0x85, 0x00,
0xae, 0x8e, 0x69, 0xa6, 0x25, 0xe0, 0x90, 0x72, 0xef, 0x3f, 0x45, 0xd0, 0x2d, 0xa6, 0xe6, 0x73, 0x96, 0x2d, 0x80, 0x87, 0xb0, 0x4f, 0xc3, 0x90, 0xe5, 0xe2, 0xc9, 0xfc, 0x22, 0x89, 0xc3, 0x33,
0x10, 0x40, 0x99, 0xb4, 0xc7, 0xf1, 0x65, 0x42, 0xc5, 0x32, 0xd7, 0x2f, 0x48, 0x99, 0xb4, 0x12, 0xd3, 0x4a, 0x5d, 0xb2, 0x0e, 0xe3, 0xf7, 0xa1, 0x67, 0x12, 0x5b, 0x52, 0x75, 0x69, 0x36, 0xf0,
0xc6, 0x27, 0xd0, 0x5b, 0x8f, 0xf7, 0x59, 0xa4, 0x62, 0x73, 0xc8, 0x06, 0x56, 0x9f, 0xac, 0x4e, 0xff, 0x5c, 0xfd, 0x00, 0x3a, 0x3a, 0x9f, 0xa9, 0x96, 0xde, 0x25, 0xd5, 0x3d, 0x78, 0x8e, 0xa0,
0x43, 0xb2, 0xfc, 0xa5, 0x2e, 0x9f, 0x79, 0xd0, 0x76, 0xc5, 0x72, 0x0e, 0x87, 0x66, 0x90, 0x11, 0x53, 0x6e, 0xc3, 0x57, 0x20, 0x7c, 0x55, 0xb0, 0xf3, 0xea, 0x0b, 0xc0, 0xae, 0x17, 0xac, 0x82,
0x96, 0xcd, 0x69, 0x58, 0x4e, 0xa0, 0x57, 0x6a, 0x52, 0x4b, 0x36, 0x98, 0x64, 0xdb, 0xd2, 0xff, 0xf1, 0x01, 0x74, 0x97, 0x2b, 0x7b, 0x1a, 0xa9, 0xbc, 0x5c, 0xb2, 0x82, 0x35, 0x17, 0xaa, 0xfd,
0x11, 0x0e, 0x36, 0x29, 0xcf, 0x21, 0x8d, 0x6b, 0x45, 0x95, 0xf1, 0x99, 0x3c, 0xde, 0xc1, 0xfd, 0x92, 0x42, 0x05, 0xdf, 0x6b, 0xe9, 0xcc, 0x8f, 0xd3, 0xb6, 0x5c, 0x1e, 0xc3, 0xbe, 0x59, 0x58,
0x1f, 0xe0, 0xa8, 0xee, 0x29, 0xde, 0xe9, 0xc5, 0x96, 0xae, 0x5a, 0xff, 0x4a, 0x57, 0x27, 0xa7, 0x84, 0xe5, 0x09, 0x0d, 0xab, 0x6d, 0xf3, 0xf6, 0x5a, 0x59, 0xc9, 0x0a, 0x8b, 0xac, 0x7b, 0x05,
0x70, 0xb8, 0x75, 0x8e, 0x1d, 0xe8, 0x9c, 0x46, 0x8b, 0x38, 0xe9, 0x5b, 0x18, 0x60, 0xff, 0xeb, 0x3f, 0xc2, 0xde, 0x2a, 0xe5, 0x15, 0x94, 0x70, 0xd9, 0x49, 0x55, 0x6e, 0xa6, 0x86, 0x1b, 0x78,
0x3c, 0x16, 0x2c, 0xef, 0x23, 0xb9, 0x96, 0xee, 0xb2, 0xbc, 0xdf, 0xc2, 0x2e, 0xd8, 0xba, 0x44, 0x20, 0xe0, 0x4e, 0xd3, 0xcf, 0xea, 0xd6, 0x28, 0xd6, 0xfa, 0xa9, 0xf5, 0xaf, 0xfb, 0xe9, 0xe0,
0x51, 0xbf, 0x3d, 0x79, 0xf9, 0xe9, 0x4d, 0x80, 0x9e, 0xdd, 0x04, 0xe8, 0xcf, 0x9b, 0x00, 0xfd, 0x18, 0xf6, 0xd7, 0xec, 0xd8, 0x85, 0xf6, 0x71, 0x34, 0x8b, 0xd3, 0x9e, 0x85, 0x01, 0x76, 0xbf,
0x72, 0x1b, 0x58, 0xcf, 0x6e, 0x03, 0xeb, 0x8f, 0xdb, 0xc0, 0xfa, 0xb6, 0xa3, 0xfe, 0x7f, 0x5e, 0x2e, 0x62, 0xc1, 0x8a, 0x1e, 0x92, 0x67, 0x19, 0x2a, 0x2b, 0x7a, 0x2d, 0xec, 0x81, 0xa3, 0xa5,
0xec, 0xab, 0xbf, 0x9b, 0x0f, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x12, 0x23, 0x4c, 0xb6, 0xa2, 0x89, 0x7a, 0xf6, 0xc9, 0x3b, 0xcf, 0x6f, 0xfa, 0xe8, 0xc5, 0x4d, 0x1f, 0xfd, 0x79, 0xd3, 0x47,
0x0a, 0x00, 0x00, 0xbf, 0xdc, 0xf6, 0xad, 0x17, 0xb7, 0x7d, 0xeb, 0xf7, 0xdb, 0xbe, 0xf5, 0x6d, 0x5b, 0x7d, 0x88,
0x5e, 0xec, 0xaa, 0xef, 0xce, 0x87, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xe8, 0x23, 0x71,
0xab, 0x0a, 0x00, 0x00,
}
func (m *RawChange) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *RawChange) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *RawChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Id) > 0 {
i -= len(m.Id)
copy(dAtA[i:], m.Id)
i = encodeVarintAclchanges(dAtA, i, uint64(len(m.Id)))
i--
dAtA[i] = 0x1a
}
if len(m.Signature) > 0 {
i -= len(m.Signature)
copy(dAtA[i:], m.Signature)
i = encodeVarintAclchanges(dAtA, i, uint64(len(m.Signature)))
i--
dAtA[i] = 0x12
}
if len(m.Payload) > 0 {
i -= len(m.Payload)
copy(dAtA[i:], m.Payload)
i = encodeVarintAclchanges(dAtA, i, uint64(len(m.Payload)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
} }
func (m *ACLChange) Marshal() (dAtA []byte, err error) { func (m *ACLChange) Marshal() (dAtA []byte, err error) {
@ -1855,6 +1962,27 @@ func encodeVarintAclchanges(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v) dAtA[offset] = uint8(v)
return base return base
} }
func (m *RawChange) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Payload)
if l > 0 {
n += 1 + l + sovAclchanges(uint64(l))
}
l = len(m.Signature)
if l > 0 {
n += 1 + l + sovAclchanges(uint64(l))
}
l = len(m.Id)
if l > 0 {
n += 1 + l + sovAclchanges(uint64(l))
}
return n
}
func (m *ACLChange) Size() (n int) { func (m *ACLChange) Size() (n int) {
if m == nil { if m == nil {
return 0 return 0
@ -2244,6 +2372,156 @@ func sovAclchanges(x uint64) (n int) {
func sozAclchanges(x uint64) (n int) { func sozAclchanges(x uint64) (n int) {
return sovAclchanges(uint64((x << 1) ^ uint64((int64(x) >> 63)))) return sovAclchanges(uint64((x << 1) ^ uint64((int64(x) >> 63))))
} }
func (m *RawChange) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclchanges
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RawChange: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RawChange: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclchanges
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthAclchanges
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthAclchanges
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...)
if m.Payload == nil {
m.Payload = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclchanges
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthAclchanges
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthAclchanges
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
if m.Signature == nil {
m.Signature = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclchanges
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthAclchanges
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthAclchanges
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Id = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAclchanges(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAclchanges
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ACLChange) Unmarshal(dAtA []byte) error { func (m *ACLChange) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -1,7 +1,13 @@
syntax = "proto3"; syntax = "proto3";
package anytype; package acl;
option go_package = "aclpb"; option go_package = "aclpb";
message RawChange {
bytes payload = 1;
bytes signature = 2;
string id = 3;
}
// the element of change tree used to store and internal apply smartBlock history // the element of change tree used to store and internal apply smartBlock history
message ACLChange { message ACLChange {
repeated string treeHeadIds = 1; repeated string treeHeadIds = 1;

View File

@ -2,8 +2,12 @@ package acltree
import ( import (
"context" "context"
"errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"go.uber.org/zap"
"sync" "sync"
) )
@ -18,6 +22,7 @@ const (
type AddResult struct { type AddResult struct {
OldHeads []string OldHeads []string
Heads []string Heads []string
Added []*aclpb.RawChange
// TODO: add summary for changes // TODO: add summary for changes
Summary AddResultSummary Summary AddResultSummary
} }
@ -27,15 +32,38 @@ type TreeUpdateListener interface {
Rebuild(tree ACLTree) Rebuild(tree ACLTree)
} }
type NoOpListener struct{}
func (n NoOpListener) Update(tree ACLTree) {}
func (n NoOpListener) Rebuild(tree ACLTree) {}
type RWLocker interface {
sync.Locker
RLock()
RUnlock()
}
var ErrNoCommonSnapshot = errors.New("trees doesn't have a common snapshot")
type ACLTree interface { type ACLTree interface {
RWLocker
ID() string
Header() *treepb.TreeHeader
ACLState() *ACLState ACLState() *ACLState
AddContent(ctx context.Context, f func(builder ChangeBuilder) error) (*Change, error) AddContent(ctx context.Context, f func(builder ChangeBuilder) error) (*aclpb.RawChange, error)
AddChanges(ctx context.Context, changes ...*Change) (AddResult, error) AddRawChanges(ctx context.Context, changes ...*aclpb.RawChange) (AddResult, error)
Heads() []string Heads() []string
Root() *Change Root() *Change
Iterate(func(change *Change) bool) Iterate(func(change *Change) bool)
IterateFrom(string, func(change *Change) bool) IterateFrom(string, func(change *Change) bool)
HasChange(string) bool HasChange(string) bool
SnapshotPath() []string
ChangesAfterCommonSnapshot(snapshotPath []string) ([]*aclpb.RawChange, error)
Storage() treestorage.TreeStorage
DebugDump() (string, error)
Close() error
} }
type aclTree struct { type aclTree struct {
@ -43,6 +71,8 @@ type aclTree struct {
accountData *account.AccountData accountData *account.AccountData
updateListener TreeUpdateListener updateListener TreeUpdateListener
id string
header *treepb.TreeHeader
fullTree *Tree fullTree *Tree
aclTreeFromStart *Tree // TODO: right now we don't use it, we can probably have only local var for now. This tree is built from start of the document aclTreeFromStart *Tree // TODO: right now we don't use it, we can probably have only local var for now. This tree is built from start of the document
aclState *ACLState aclState *ACLState
@ -90,6 +120,14 @@ func BuildACLTree(
if err != nil { if err != nil {
return nil, err return nil, err
} }
aclTree.id, err = t.TreeID()
if err != nil {
return nil, err
}
aclTree.header, err = t.Header()
if err != nil {
return nil, err
}
listener.Rebuild(aclTree) listener.Rebuild(aclTree)
@ -192,17 +230,25 @@ func (a *aclTree) rebuildFromStorage(fromStart bool) error {
return nil return nil
} }
func (a *aclTree) ID() string {
return a.id
}
func (a *aclTree) Header() *treepb.TreeHeader {
return a.header
}
func (a *aclTree) ACLState() *ACLState { func (a *aclTree) ACLState() *ACLState {
a.RLock()
defer a.RUnlock()
return a.aclState return a.aclState
} }
func (a *aclTree) AddContent(ctx context.Context, build func(builder ChangeBuilder) error) (*Change, error) { func (a *aclTree) Storage() treestorage.TreeStorage {
return a.treeStorage
}
func (a *aclTree) AddContent(ctx context.Context, build func(builder ChangeBuilder) error) (*aclpb.RawChange, error) {
// TODO: add snapshot creation logic // TODO: add snapshot creation logic
a.Lock()
defer func() { defer func() {
a.Unlock()
// TODO: should this be called in a separate goroutine to prevent accidental cycles (tree->updater->tree) // TODO: should this be called in a separate goroutine to prevent accidental cycles (tree->updater->tree)
a.updateListener.Update(a) a.updateListener.Update(a)
}() }()
@ -218,12 +264,13 @@ func (a *aclTree) AddContent(ctx context.Context, build func(builder ChangeBuild
return nil, err return nil, err
} }
a.fullTree.AddFast(ch) a.fullTree.AddFast(ch)
rawCh := &aclpb.RawChange{
err = a.treeStorage.AddRawChange(&treestorage.RawChange{
Payload: marshalled, Payload: marshalled,
Signature: ch.Signature(), Signature: ch.Signature(),
Id: ch.Id, Id: ch.Id,
}) }
err = a.treeStorage.AddRawChange(rawCh)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -232,15 +279,24 @@ func (a *aclTree) AddContent(ctx context.Context, build func(builder ChangeBuild
if err != nil { if err != nil {
return nil, err return nil, err
} }
return ch, nil return rawCh, nil
} }
func (a *aclTree) AddChanges(ctx context.Context, changes ...*Change) (AddResult, error) { func (a *aclTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawChange) (AddResult, error) {
a.Lock()
// TODO: make proper error handling, because there are a lot of corner cases where this will break // TODO: make proper error handling, because there are a lot of corner cases where this will break
var err error var err error
var mode Mode var mode Mode
var changes []*Change // TODO: = addChangesBuf[:0] ...
for _, ch := range rawChanges {
change, err := NewFromRawChange(ch)
// TODO: think what if we will have incorrect signatures on rawChanges, how everything will work
if err != nil {
continue
}
changes = append(changes, change)
}
defer func() { defer func() {
if err != nil { if err != nil {
return return
@ -256,7 +312,6 @@ func (a *aclTree) AddChanges(ctx context.Context, changes ...*Change) (AddResult
return return
} }
a.Unlock()
switch mode { switch mode {
case Append: case Append:
a.updateListener.Update(a) a.updateListener.Update(a)
@ -267,6 +322,16 @@ func (a *aclTree) AddChanges(ctx context.Context, changes ...*Change) (AddResult
} }
}() }()
getAddedChanges := func() []*aclpb.RawChange {
var added []*aclpb.RawChange
for _, ch := range rawChanges {
if _, exists := a.fullTree.attached[ch.Id]; exists {
added = append(added, ch)
}
}
return added
}
for _, ch := range changes { for _, ch := range changes {
err = a.treeStorage.AddChange(ch) err = a.treeStorage.AddChange(ch)
if err != nil { if err != nil {
@ -297,6 +362,7 @@ func (a *aclTree) AddChanges(ctx context.Context, changes ...*Change) (AddResult
return AddResult{ return AddResult{
OldHeads: prevHeads, OldHeads: prevHeads,
Heads: a.fullTree.Heads(), Heads: a.fullTree.Heads(),
Added: getAddedChanges(),
Summary: AddResultSummaryRebuild, Summary: AddResultSummaryRebuild,
}, nil }, nil
default: default:
@ -310,26 +376,21 @@ func (a *aclTree) AddChanges(ctx context.Context, changes ...*Change) (AddResult
return AddResult{ return AddResult{
OldHeads: prevHeads, OldHeads: prevHeads,
Heads: a.fullTree.Heads(), Heads: a.fullTree.Heads(),
Added: getAddedChanges(),
Summary: AddResultSummaryAppend, Summary: AddResultSummaryAppend,
}, nil }, nil
} }
} }
func (a *aclTree) Iterate(f func(change *Change) bool) { func (a *aclTree) Iterate(f func(change *Change) bool) {
a.RLock()
defer a.RUnlock()
a.fullTree.Iterate(a.fullTree.RootId(), f) a.fullTree.Iterate(a.fullTree.RootId(), f)
} }
func (a *aclTree) IterateFrom(s string, f func(change *Change) bool) { func (a *aclTree) IterateFrom(s string, f func(change *Change) bool) {
a.RLock()
defer a.RUnlock()
a.fullTree.Iterate(s, f) a.fullTree.Iterate(s, f)
} }
func (a *aclTree) HasChange(s string) bool { func (a *aclTree) HasChange(s string) bool {
a.RLock()
defer a.RUnlock()
_, attachedExists := a.fullTree.attached[s] _, attachedExists := a.fullTree.attached[s]
_, unattachedExists := a.fullTree.unAttached[s] _, unattachedExists := a.fullTree.unAttached[s]
_, invalidExists := a.fullTree.invalidChanges[s] _, invalidExists := a.fullTree.invalidChanges[s]
@ -337,13 +398,123 @@ func (a *aclTree) HasChange(s string) bool {
} }
func (a *aclTree) Heads() []string { func (a *aclTree) Heads() []string {
a.RLock()
defer a.RUnlock()
return a.fullTree.Heads() return a.fullTree.Heads()
} }
func (a *aclTree) Root() *Change { func (a *aclTree) Root() *Change {
a.RLock()
defer a.RUnlock()
return a.fullTree.Root() return a.fullTree.Root()
} }
func (a *aclTree) Close() error {
return nil
}
func (a *aclTree) SnapshotPath() []string {
// TODO: think about caching this
var path []string
// TODO: think that the user may have not all of the snapshots locally
currentSnapshotId := a.fullTree.RootId()
for currentSnapshotId != "" {
sn, err := a.treeBuilder.loadChange(currentSnapshotId)
if err != nil {
break
}
path = append(path, currentSnapshotId)
currentSnapshotId = sn.SnapshotId
}
return path
}
func (a *aclTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawChange, error) {
// TODO: think about when the clients will have their full acl tree and thus full snapshots
// but no changes after some of the snapshots
var (
isNewDocument = len(theirPath) == 0
ourPath = a.SnapshotPath()
// by default returning everything we have
commonSnapshot = ourPath[len(ourPath)-1] // TODO: root snapshot, probably it is better to have a specific method in treestorage
err error
)
// if this is non-empty request
if !isNewDocument {
commonSnapshot, err = a.commonSnapshotForTwoPaths(ourPath, theirPath)
if err != nil {
return nil, err
}
}
var rawChanges []*aclpb.RawChange
// using custom load function to skip verification step and save raw changes
load := func(id string) (*Change, error) {
raw, err := a.treeStorage.GetChange(context.Background(), id)
if err != nil {
return nil, err
}
aclChange, err := a.treeBuilder.makeUnverifiedACLChange(raw)
if err != nil {
return nil, err
}
ch := NewChange(id, aclChange)
rawChanges = append(rawChanges, raw)
return ch, nil
}
// we presume that we have everything after the common snapshot, though this may not be the case in case of clients and only ACL tree changes
log.With(
zap.Strings("heads", a.fullTree.Heads()),
zap.String("breakpoint", commonSnapshot),
zap.String("id", a.id)).
Debug("getting all changes from common snapshot")
_, err = a.treeBuilder.dfs(a.fullTree.Heads(), commonSnapshot, load)
if err != nil {
return nil, err
}
if isNewDocument {
// adding snapshot to raw changes
_, err = load(commonSnapshot)
if err != nil {
return nil, err
}
}
log.With(
zap.Int("len(changes)", len(rawChanges)),
zap.String("id", a.id)).
Debug("sending all changes after common snapshot")
return rawChanges, nil
}
func (a *aclTree) DebugDump() (string, error) {
return a.fullTree.Graph()
}
func (a *aclTree) commonSnapshotForTwoPaths(ourPath []string, theirPath []string) (string, error) {
var i int
var j int
log.With(zap.Strings("our path", ourPath), zap.Strings("their path", theirPath)).
Debug("finding common snapshot for two paths")
OuterLoop:
// find starting point from the right
for i = len(ourPath) - 1; i >= 0; i-- {
for j = len(theirPath) - 1; j >= 0; j-- {
// most likely there would be only one comparison, because mostly the snapshot path will start from the root for nodes
if ourPath[i] == theirPath[j] {
break OuterLoop
}
}
}
if i < 0 || j < 0 {
return "", ErrNoCommonSnapshot
}
// find last common element of the sequence moving from right to left
for i >= 0 && j >= 0 {
if ourPath[i] == theirPath[j] {
i--
j--
}
}
return ourPath[i+1], nil
}

View File

@ -27,7 +27,7 @@ func TestACLTree_UserJoinBuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
@ -62,24 +62,16 @@ func TestACLTree_UserJoinUpdate_Append(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
if err != nil { if err != nil {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
rawChanges := thr.GetUpdates("append") rawChanges := thr.GetUpdates("append")
var changes []*Change res, err := tree.AddRawChanges(context.Background(), rawChanges...)
for _, ch := range rawChanges {
newCh, err := NewFromRawChange(ch)
if err != nil {
t.Fatalf("should be able to create change from raw: %v", err)
}
changes = append(changes, newCh)
}
res, err := tree.AddChanges(context.Background(), changes...)
assert.Equal(t, res.Summary, AddResultSummaryAppend) assert.Equal(t, res.Summary, AddResultSummaryAppend)
aclState := tree.ACLState() aclState := tree.ACLState()
@ -112,7 +104,7 @@ func TestACLTree_UserJoinUpdate_Rebuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
@ -120,16 +112,7 @@ func TestACLTree_UserJoinUpdate_Rebuild(t *testing.T) {
t.Fatalf("should Build acl ACLState without err: %v", err) t.Fatalf("should Build acl ACLState without err: %v", err)
} }
rawChanges := thr.GetUpdates("rebuild") rawChanges := thr.GetUpdates("rebuild")
var changes []*Change res, err := tree.AddRawChanges(context.Background(), rawChanges...)
for _, ch := range rawChanges {
newCh, err := NewFromRawChange(ch)
if err != nil {
t.Fatalf("should be able to create change from raw: %v", err)
}
changes = append(changes, newCh)
}
res, err := tree.AddChanges(context.Background(), changes...)
assert.Equal(t, res.Summary, AddResultSummaryRebuild) assert.Equal(t, res.Summary, AddResultSummaryRebuild)
aclState := tree.ACLState() aclState := tree.ACLState()
@ -163,7 +146,7 @@ func TestACLTree_UserRemoveBuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
@ -194,7 +177,7 @@ func TestACLTree_UserRemoveBeforeBuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
@ -226,7 +209,7 @@ func TestACLTree_InvalidSnapshotBuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)
@ -257,7 +240,7 @@ func TestACLTree_ValidSnapshotBuild(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
listener := &mockListener{} listener := &mockListener{}
tree, err := BuildACLTree(thr, accountData, listener) tree, err := BuildACLTree(thr, accountData, listener)

View File

@ -2,17 +2,21 @@ package acltree
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/gogo/protobuf/proto"
) )
func BuildTreeStorageWithACL( func CreateNewTreeStorageWithACL(
acc *account.AccountData, acc *account.AccountData,
build func(builder ChangeBuilder) error, build func(builder ChangeBuilder) error,
create func(change *treestorage.RawChange) (treestorage.TreeStorage, error)) (treestorage.TreeStorage, error) { create treestorage.CreatorFunc) (treestorage.TreeStorage, error) {
bld := newChangeBuilder() bld := newChangeBuilder()
bld.Init( bld.Init(
newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519Decoder()), newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519PubKeyDecoder()),
&Tree{}, &Tree{},
acc) acc)
err := build(bld) err := build(bld)
@ -26,13 +30,17 @@ func BuildTreeStorageWithACL(
return nil, err return nil, err
} }
rawChange := &treestorage.RawChange{ rawChange := &aclpb.RawChange{
Payload: payload, Payload: payload,
Signature: change.Signature(), Signature: change.Signature(),
Id: change.CID(), Id: change.CID(),
} }
header, id, err := createTreeHeaderAndId(rawChange)
if err != nil {
return nil, err
}
thr, err := create(rawChange) thr, err := create(id, header, []*aclpb.RawChange{rawChange})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -43,3 +51,20 @@ func BuildTreeStorageWithACL(
} }
return thr, nil return thr, nil
} }
func createTreeHeaderAndId(change *aclpb.RawChange) (*treepb.TreeHeader, string, error) {
header := &treepb.TreeHeader{
FirstChangeId: change.Id,
IsWorkspace: false,
}
marshalledHeader, err := proto.Marshal(header)
if err != nil {
return nil, "", err
}
treeId, err := cid.NewCIDFromBytes(marshalledHeader)
if err != nil {
return nil, "", err
}
return header, treeId, nil
}

View File

@ -19,7 +19,7 @@ func Test_BuildTreeStorageWithACL(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
thr, err := BuildTreeStorageWithACL( thr, err := CreateNewTreeStorageWithACL(
data, data,
func(builder ChangeBuilder) error { func(builder ChangeBuilder) error {
return builder.UserAdd( return builder.UserAdd(

View File

@ -3,7 +3,6 @@ package acltree
import ( import (
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
@ -47,7 +46,7 @@ func (ch *Change) IsACLChange() bool {
return ch.Content.GetAclData() != nil return ch.Content.GetAclData() != nil
} }
func NewFromRawChange(rawChange *treestorage.RawChange) (*Change, error) { func NewFromRawChange(rawChange *aclpb.RawChange) (*Change, error) {
unmarshalled := &aclpb.ACLChange{} unmarshalled := &aclpb.ACLChange{}
err := proto.Unmarshal(rawChange.Payload, unmarshalled) err := proto.Unmarshal(rawChange.Payload, unmarshalled)
if err != nil { if err != nil {

View File

@ -73,7 +73,7 @@ func (c *changeLoader) verify(identity string, payload, signature []byte) (isVer
return identityKey.Verify(payload, signature) return identityKey.Verify(payload, signature)
} }
func (c *changeLoader) makeVerifiedACLChange(change *treestorage.RawChange) (aclChange *aclpb.ACLChange, err error) { func (c *changeLoader) makeVerifiedACLChange(change *aclpb.RawChange) (aclChange *aclpb.ACLChange, err error) {
aclChange = new(aclpb.ACLChange) aclChange = new(aclpb.ACLChange)
// TODO: think what should we do with such cases, because this can be used by attacker to break our Tree // TODO: think what should we do with such cases, because this can be used by attacker to break our Tree
@ -91,3 +91,9 @@ func (c *changeLoader) makeVerifiedACLChange(change *treestorage.RawChange) (acl
} }
return return
} }
func (c *changeLoader) makeUnverifiedACLChange(change *aclpb.RawChange) (aclChange *aclpb.ACLChange, err error) {
aclChange = new(aclpb.ACLChange)
err = proto.Unmarshal(change.Payload, aclChange)
return
}

View File

@ -6,7 +6,6 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
) )
@ -135,13 +134,16 @@ func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error)
return return
} }
tb.tree.AddFast(ch) tb.tree.AddFast(ch)
changes, err := tb.dfs(heads, breakpoint) changes, err := tb.dfs(heads, breakpoint, tb.loadChange)
tb.tree.AddFast(changes...) tb.tree.AddFast(changes...)
return return
} }
func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, err error) { func (tb *treeBuilder) dfs(
heads []string,
breakpoint string,
load func(string) (*Change, error)) (buf []*Change, err error) {
stack := make([]string, len(heads), len(heads)*2) stack := make([]string, len(heads), len(heads)*2)
copy(stack, heads) copy(stack, heads)
@ -154,7 +156,7 @@ func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, er
continue continue
} }
ch, err := tb.loadChange(id) ch, err := load(id)
if err != nil { if err != nil {
continue continue
} }

View File

@ -83,6 +83,7 @@ func (t *Tree) Graph() (data string, err error) {
// } // }
// chSymbs = append(chSymbs, res) // chSymbs = append(chSymbs, res)
//} //}
chSymbs = append(chSymbs, "DEC")
} }
shortId := c.Id shortId := c.Id

View File

@ -17,6 +17,7 @@ type PlainTextDocument interface {
AddText(ctx context.Context, text string) error AddText(ctx context.Context, text string) error
} }
// TODO: this struct is not thread-safe, so use it wisely :-)
type plainTextDocument struct { type plainTextDocument struct {
heads []string heads []string
aclTree acltree.ACLTree aclTree acltree.ACLTree
@ -117,7 +118,7 @@ func NewInMemoryPlainTextDocument(acc *account.AccountData, text string) (PlainT
func NewPlainTextDocument( func NewPlainTextDocument(
acc *account.AccountData, acc *account.AccountData,
create func(change *treestorage.RawChange) (treestorage.TreeStorage, error), create treestorage.CreatorFunc,
text string) (PlainTextDocument, error) { text string) (PlainTextDocument, error) {
changeBuilder := func(builder acltree.ChangeBuilder) error { changeBuilder := func(builder acltree.ChangeBuilder) error {
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin) err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin)
@ -127,7 +128,7 @@ func NewPlainTextDocument(
builder.AddChangeContent(createInitialChangeContent(text)) builder.AddChangeContent(createInitialChangeContent(text))
return nil return nil
} }
t, err := acltree.BuildTreeStorageWithACL( t, err := acltree.CreateNewTreeStorageWithACL(
acc, acc,
changeBuilder, changeBuilder,
create) create)

View File

@ -18,7 +18,7 @@ func TestDocument_NewPlainTextDocument(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text") doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text")
@ -36,7 +36,7 @@ func TestDocument_PlainTextDocument_AddText(t *testing.T) {
Identity: keychain.GetIdentity("A"), Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
Decoder: signingkey.NewEd25519Decoder(), Decoder: signingkey.NewEd25519PubKeyDecoder(),
} }
doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text") doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text")

View File

@ -32,7 +32,7 @@ func NewKeychain() *Keychain {
GeneratedIdentities: map[string]string{}, GeneratedIdentities: map[string]string{},
ReadKeys: map[string]*SymKey{}, ReadKeys: map[string]*SymKey{},
ReadKeysByHash: map[uint64]*SymKey{}, ReadKeysByHash: map[uint64]*SymKey{},
coder: signingkey.NewEd25519Decoder(), coder: signingkey.NewEd25519PubKeyDecoder(),
} }
} }

View File

@ -7,7 +7,6 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
testpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb" testpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/yamltests" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/yamltests"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
storagepb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" storagepb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
@ -87,7 +86,7 @@ func (t *TreeStorageBuilder) Heads() ([]string, error) {
return t.heads, nil return t.heads, nil
} }
func (t *TreeStorageBuilder) AddRawChange(change *treestorage.RawChange) error { func (t *TreeStorageBuilder) AddRawChange(change *aclpb.RawChange) error {
aclChange := new(aclpb.ACLChange) aclChange := new(aclpb.ACLChange)
var err error var err error
@ -165,12 +164,12 @@ func (t *TreeStorageBuilder) RemoveOrphans(orphans ...string) error {
return nil return nil
} }
func (t *TreeStorageBuilder) GetChange(ctx context.Context, recordID string) (*treestorage.RawChange, error) { func (t *TreeStorageBuilder) GetChange(ctx context.Context, recordID string) (*aclpb.RawChange, error) {
return t.getChange(recordID, t.allChanges), nil return t.getChange(recordID, t.allChanges), nil
} }
func (t *TreeStorageBuilder) GetUpdates(useCase string) []*treestorage.RawChange { func (t *TreeStorageBuilder) GetUpdates(useCase string) []*aclpb.RawChange {
var res []*treestorage.RawChange var res []*aclpb.RawChange
update := t.updates[useCase] update := t.updates[useCase]
for _, ch := range update.changes { for _, ch := range update.changes {
rawCh := t.getChange(ch.id, update.changes) rawCh := t.getChange(ch.id, update.changes)
@ -183,7 +182,7 @@ func (t *TreeStorageBuilder) Header() (*storagepb.TreeHeader, error) {
return t.header, nil return t.header, nil
} }
func (t *TreeStorageBuilder) getChange(changeId string, m map[string]*treeChange) *treestorage.RawChange { func (t *TreeStorageBuilder) getChange(changeId string, m map[string]*treeChange) *aclpb.RawChange {
rec := m[changeId] rec := m[changeId]
if rec.changesDataDecrypted != nil { if rec.changesDataDecrypted != nil {
@ -205,7 +204,7 @@ func (t *TreeStorageBuilder) getChange(changeId string, m map[string]*treeChange
panic("should be able to sign final acl message!") panic("should be able to sign final acl message!")
} }
transformedRec := &treestorage.RawChange{ transformedRec := &aclpb.RawChange{
Payload: aclMarshaled, Payload: aclMarshaled,
Signature: signature, Signature: signature,
Id: changeId, Id: changeId,

View File

@ -4,8 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"sync" "sync"
@ -16,34 +16,30 @@ type inMemoryTreeStorage struct {
header *treepb.TreeHeader header *treepb.TreeHeader
heads []string heads []string
orphans []string orphans []string
changes map[string]*RawChange changes map[string]*aclpb.RawChange
sync.RWMutex sync.RWMutex
} }
func NewInMemoryTreeStorage(firstChange *RawChange) (TreeStorage, error) { type CreatorFunc = func(string, *treepb.TreeHeader, []*aclpb.RawChange) (TreeStorage, error)
header := &treepb.TreeHeader{
FirstChangeId: firstChange.Id,
IsWorkspace: false,
}
marshalledHeader, err := proto.Marshal(header)
if err != nil {
return nil, err
}
treeId, err := cid.NewCIDFromBytes(marshalledHeader)
if err != nil {
return nil, err
}
changes := make(map[string]*RawChange) func NewInMemoryTreeStorage(
changes[firstChange.Id] = firstChange treeId string,
header *treepb.TreeHeader,
changes []*aclpb.RawChange) (TreeStorage, error) {
allChanges := make(map[string]*aclpb.RawChange)
var orphans []string
for _, ch := range changes {
allChanges[ch.Id] = ch
orphans = append(orphans, ch.Id)
}
return &inMemoryTreeStorage{ return &inMemoryTreeStorage{
id: treeId, id: treeId,
header: header, header: header,
heads: []string{firstChange.Id}, heads: nil,
orphans: nil, orphans: orphans,
changes: changes, changes: allChanges,
RWMutex: sync.RWMutex{}, RWMutex: sync.RWMutex{},
}, nil }, nil
} }
@ -97,7 +93,7 @@ func (t *inMemoryTreeStorage) AddOrphans(orphans ...string) error {
return nil return nil
} }
func (t *inMemoryTreeStorage) AddRawChange(change *RawChange) error { func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawChange) error {
t.Lock() t.Lock()
defer t.Unlock() defer t.Unlock()
// TODO: better to do deep copy // TODO: better to do deep copy
@ -116,7 +112,7 @@ func (t *inMemoryTreeStorage) AddChange(change aclchanges.Change) error {
if err != nil { if err != nil {
return err return err
} }
rawChange := &RawChange{ rawChange := &aclpb.RawChange{
Payload: fullMarshalledChange, Payload: fullMarshalledChange,
Signature: signature, Signature: signature,
Id: id, Id: id,
@ -125,7 +121,7 @@ func (t *inMemoryTreeStorage) AddChange(change aclchanges.Change) error {
return nil return nil
} }
func (t *inMemoryTreeStorage) GetChange(ctx context.Context, changeId string) (*RawChange, error) { func (t *inMemoryTreeStorage) GetChange(ctx context.Context, changeId string) (*aclpb.RawChange, error) {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
if res, exists := t.changes[changeId]; exists { if res, exists := t.changes[changeId]; exists {
@ -133,3 +129,35 @@ func (t *inMemoryTreeStorage) GetChange(ctx context.Context, changeId string) (*
} }
return nil, fmt.Errorf("could not get change with id: %s", changeId) return nil, fmt.Errorf("could not get change with id: %s", changeId)
} }
type inMemoryTreeStorageProvider struct {
trees map[string]TreeStorage
sync.RWMutex
}
func (i *inMemoryTreeStorageProvider) TreeStorage(treeId string) (TreeStorage, error) {
i.RLock()
defer i.RUnlock()
if tree, exists := i.trees[treeId]; exists {
return tree, nil
}
return nil, ErrUnknownTreeId
}
func (i *inMemoryTreeStorageProvider) CreateTreeStorage(treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) (TreeStorage, error) {
i.Lock()
defer i.Unlock()
res, err := NewInMemoryTreeStorage(treeId, header, changes)
if err != nil {
return nil, err
}
i.trees[treeId] = res
return res, nil
}
func NewInMemoryTreeStorageProvider() Provider {
return &inMemoryTreeStorageProvider{
trees: make(map[string]TreeStorage),
}
}

View File

@ -0,0 +1,14 @@
package treestorage
import (
"errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
)
var ErrUnknownTreeId = errors.New("tree does not exist")
type Provider interface {
TreeStorage(treeId string) (TreeStorage, error)
CreateTreeStorage(treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) (TreeStorage, error)
}

View File

@ -3,6 +3,7 @@ package treestorage
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
) )
@ -16,15 +17,9 @@ type TreeStorage interface {
RemoveOrphans(orphan ...string) error RemoveOrphans(orphan ...string) error
AddOrphans(orphan ...string) error AddOrphans(orphan ...string) error
AddRawChange(change *RawChange) error AddRawChange(change *aclpb.RawChange) error
AddChange(change aclchanges.Change) error AddChange(change aclchanges.Change) error
// TODO: have methods with raw changes also // TODO: have methods with raw changes also
GetChange(ctx context.Context, recordID string) (*RawChange, error) GetChange(ctx context.Context, recordID string) (*aclpb.RawChange, error)
}
type RawChange struct {
Payload []byte
Signature []byte
Id string
} }

View File

@ -1,5 +1,5 @@
syntax = "proto3"; syntax = "proto3";
package anytype; package tree;
option go_package = "treepb"; option go_package = "treepb";
message TreeHeader { message TreeHeader {

View File

@ -75,7 +75,7 @@ func (m *TreeHeader) GetIsWorkspace() bool {
} }
func init() { func init() {
proto.RegisterType((*TreeHeader)(nil), "anytype.TreeHeader") proto.RegisterType((*TreeHeader)(nil), "tree.TreeHeader")
} }
func init() { func init() {
@ -83,18 +83,18 @@ func init() {
} }
var fileDescriptor_e7d760b855878644 = []byte{ var fileDescriptor_e7d760b855878644 = []byte{
// 170 bytes of a gzipped FileDescriptorProto // 165 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7,
0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05, 0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05,
0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88, 0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88,
0x3d, 0x31, 0xaf, 0xb2, 0xa4, 0xb2, 0x20, 0x55, 0x29, 0x84, 0x8b, 0x2b, 0xa4, 0x28, 0x35, 0xd5, 0x05, 0xc4, 0x56, 0x0a, 0xe1, 0xe2, 0x0a, 0x29, 0x4a, 0x4d, 0xf5, 0x48, 0x4d, 0x4c, 0x49, 0x2d,
0x23, 0x35, 0x31, 0x25, 0xb5, 0x48, 0x48, 0x85, 0x8b, 0x37, 0x2d, 0xb3, 0xa8, 0xb8, 0xc4, 0x39, 0x12, 0x52, 0xe1, 0xe2, 0x4d, 0xcb, 0x2c, 0x2a, 0x2e, 0x71, 0xce, 0x48, 0xcc, 0x4b, 0x4f, 0xf5,
0x23, 0x31, 0x2f, 0x3d, 0xd5, 0x33, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0x55, 0x50, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x42, 0x15, 0x14, 0x52, 0xe0, 0xe2, 0xce, 0x2c,
0x48, 0x81, 0x8b, 0x3b, 0xb3, 0x38, 0x3c, 0xbf, 0x28, 0xbb, 0xb8, 0x20, 0x31, 0x39, 0x55, 0x82, 0x0e, 0xcf, 0x2f, 0xca, 0x2e, 0x2e, 0x48, 0x4c, 0x4e, 0x95, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x08,
0x49, 0x81, 0x51, 0x83, 0x23, 0x08, 0x59, 0xc8, 0x49, 0xe1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0x42, 0x16, 0x72, 0x52, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x36,
0x8f, 0xe5, 0x18, 0xa2, 0xd8, 0x20, 0x4e, 0x4a, 0x62, 0x03, 0xbb, 0xc3, 0x18, 0x10, 0x00, 0x00, 0x88, 0x7b, 0x92, 0xd8, 0xc0, 0x8e, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x09, 0x4f, 0xc6,
0xff, 0xff, 0xb1, 0x3f, 0x66, 0x17, 0xb7, 0x00, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0x00,
} }
func (m *TreeHeader) Marshal() (dAtA []byte, err error) { func (m *TreeHeader) Marshal() (dAtA []byte, err error) {

View File

@ -10,9 +10,10 @@ import (
) )
var ( var (
ErrClosed = errors.New("object cache closed") ErrClosed = errors.New("object cache closed")
ErrExists = errors.New("object exists") ErrExists = errors.New("object exists")
ErrTimeout = errors.New("loading object timed out") ErrTimeout = errors.New("loading object timed out")
ErrNotExists = errors.New("object not exists")
) )
var ( var (
@ -20,10 +21,6 @@ var (
defaultGC = 20 * time.Second defaultGC = 20 * time.Second
) )
type key int
const CacheTimeout key = 0
var log = logger.NewNamed("ocache") var log = logger.NewNamed("ocache")
type LoadFunc func(ctx context.Context, id string) (value Object, err error) type LoadFunc func(ctx context.Context, id string) (value Object, err error)
@ -61,7 +58,9 @@ func New(loadFunc LoadFunc, opts ...Option) OCache {
for _, o := range opts { for _, o := range opts {
o(c) o(c)
} }
go c.ticker() if c.ttl != 0 {
go c.ticker()
}
return c return c
} }
@ -99,6 +98,8 @@ type OCache interface {
// Increases the object refs counter on successful // Increases the object refs counter on successful
// When 'loadFunc' returns a non-nil error, an object will not be stored to cache // When 'loadFunc' returns a non-nil error, an object will not be stored to cache
Get(ctx context.Context, id string) (value Object, err error) Get(ctx context.Context, id string) (value Object, err error)
// Pick returns value if it's presents in cache (will not call loadFunc)
Pick(id string) (value Object, err error)
// Add adds new object to cache // Add adds new object to cache
// Returns error when object exists // Returns error when object exists
Add(id string, value Object) (err error) Add(id string, value Object) (err error)
@ -154,28 +155,28 @@ func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
e.refCount++ e.refCount++
c.mu.Unlock() c.mu.Unlock()
timeout := ctx.Value(CacheTimeout)
if load { if load {
if timeout != nil { go c.load(ctx, id, e)
go c.load(ctx, id, e)
} else {
c.load(ctx, id, e)
}
} }
select {
if timeout != nil { case <-ctx.Done():
duration := timeout.(time.Duration) return nil, ctx.Err()
select { case <-e.load:
case <-e.load:
return e.value, e.loadErr
case <-time.After(duration):
return nil, ErrTimeout
}
} }
<-e.load
return e.value, e.loadErr return e.value, e.loadErr
} }
func (c *oCache) Pick(id string) (value Object, err error) {
c.mu.Lock()
val, ok := c.data[id]
c.mu.Unlock()
if !ok {
return nil, ErrNotExists
}
<-val.load
return val.value, val.loadErr
}
func (c *oCache) load(ctx context.Context, id string, e *entry) { func (c *oCache) load(ctx context.Context, id string, e *entry) {
defer close(e.load) defer close(e.load)
value, err := c.loadFunc(ctx, id) value, err := c.loadFunc(ctx, id)

View File

@ -92,6 +92,20 @@ func TestOCache_Get(t *testing.T) {
_, err := c.Get(context.TODO(), "id") _, err := c.Get(context.TODO(), "id")
assert.Equal(t, ErrClosed, err) assert.Equal(t, ErrClosed, err)
}) })
t.Run("context cancel", func(t *testing.T) {
c := New(func(ctx context.Context, id string) (value Object, err error) {
time.Sleep(time.Second / 3)
return &testObject{
name: "id",
}, nil
})
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err := c.Get(ctx, "id")
assert.Equal(t, context.Canceled, err)
assert.NoError(t, c.Close())
})
} }
func TestOCache_GC(t *testing.T) { func TestOCache_GC(t *testing.T) {

View File

@ -0,0 +1,73 @@
package account
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
)
const CName = "account"
type Service interface {
Account() *account.AccountData
}
type service struct {
accountData *account.AccountData
peerId string
}
func (s *service) Account() *account.AccountData {
return s.accountData
}
type StaticAccount struct {
SigningKey string `yaml:"signingKey"`
EncryptionKey string `yaml:"encryptionKey"`
}
func New() app.Component {
return &service{}
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
cfg := a.MustComponent(config.CName).(*config.Config)
// decoding our keys
privateEncryptionDecoder := encryptionkey.NewRSAPrivKeyDecoder()
privateSigningDecoder := signingkey.NewEDPrivKeyDecoder()
publicSigningDecoder := signingkey.NewEDPubKeyDecoder()
acc := cfg.Account
decodedEncryptionKey, err := privateEncryptionDecoder.DecodeFromString(acc.EncryptionKey)
if err != nil {
return err
}
decodedSigningKey, err := privateSigningDecoder.DecodeFromString(acc.SigningKey)
if err != nil {
return err
}
signKey := decodedSigningKey.(signingkey.PrivKey)
identity, err := publicSigningDecoder.EncodeToString(signKey.GetPublic())
if err != nil {
return err
}
// TODO: using acl lib format basically, but we should simplify this
s.accountData = &account.AccountData{
Identity: identity,
SignKey: signKey,
EncKey: decodedEncryptionKey.(encryptionkey.PrivKey),
Decoder: signingkey.NewEd25519PubKeyDecoder(),
}
s.peerId = acc.PeerId
return nil
}
func (s *service) Name() (name string) {
return CName
}

135
service/api/service.go Normal file
View File

@ -0,0 +1,135 @@
package api
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/document"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
"go.uber.org/zap"
"io"
"net/http"
"time"
)
const CName = "APIService"
var log = logger.NewNamed("api")
func New() app.Component {
return &service{}
}
type service struct {
treeCache treecache.Service
documentService document.Service
srv *http.Server
cfg *config.Config
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
s.documentService = a.MustComponent(document.CName).(document.Service)
s.cfg = a.MustComponent(config.CName).(*config.Config)
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
defer func() {
if err == nil {
log.With(zap.String("port", s.cfg.APIServer.Port)).Info("api server started running")
}
}()
s.srv = &http.Server{
Addr: fmt.Sprintf(":%s", s.cfg.APIServer.Port),
}
mux := http.NewServeMux()
mux.HandleFunc("/treeDump", s.treeDump)
mux.HandleFunc("/createDocument", s.createDocument)
mux.HandleFunc("/appendDocument", s.appendDocument)
s.srv.Handler = mux
go s.runServer()
return nil
}
func (s *service) runServer() {
err := s.srv.ListenAndServe()
if err != nil {
log.With(zap.Error(err)).Error("could not run api server")
}
}
func (s *service) Close(ctx context.Context) (err error) {
return s.srv.Shutdown(ctx)
}
func (s *service) treeDump(w http.ResponseWriter, req *http.Request) {
var (
query = req.URL.Query()
treeId = query.Get("treeId")
dump string
err error
)
err = s.treeCache.Do(context.Background(), treeId, func(tree acltree.ACLTree) error {
dump, err = tree.DebugDump()
if err != nil {
return err
}
return nil
})
if err != nil {
sendText(w, http.StatusInternalServerError, err.Error())
return
}
sendText(w, http.StatusOK, dump)
}
func (s *service) createDocument(w http.ResponseWriter, req *http.Request) {
var (
query = req.URL.Query()
text = query.Get("text")
)
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*30)
treeId, err := s.documentService.CreateDocument(timeoutCtx, fmt.Sprintf("created document with id: %s", text))
cancel()
if err != nil {
sendText(w, http.StatusInternalServerError, err.Error())
return
}
sendText(w, http.StatusOK, treeId)
}
func (s *service) appendDocument(w http.ResponseWriter, req *http.Request) {
var (
query = req.URL.Query()
text = query.Get("text")
treeId = query.Get("treeId")
)
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second*30)
err := s.documentService.UpdateDocument(timeoutCtx, treeId, text)
cancel()
if err != nil {
sendText(w, http.StatusInternalServerError, err.Error())
return
}
sendText(w, http.StatusOK, fmt.Sprintf("updated document with id: %s with text: %s", treeId, text))
}
func sendText(r http.ResponseWriter, code int, body string) {
r.Header().Set("Content-Type", "text/plain")
r.WriteHeader(code)
_, err := io.WriteString(r, fmt.Sprintf("%s\n", body))
if err != nil {
log.Error("writing response failed", zap.Error(err))
}
}

View File

@ -0,0 +1,84 @@
package example
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"go.uber.org/zap"
"strings"
"time"
)
var log = logger.NewNamed("example")
type Example struct {
pool pool.Pool
peerConf config.PeerList
}
func (e *Example) Init(ctx context.Context, a *app.App) (err error) {
e.pool = a.MustComponent(pool.CName).(pool.Pool)
e.peerConf = a.MustComponent(config.CName).(*config.Config).PeerList
// subscribe for sync messages
e.pool.AddHandler(syncproto.MessageType_MessageTypeSync, e.syncHandler)
return
}
func (e *Example) Name() (name string) {
return "example"
}
func (e *Example) Run(ctx context.Context) (err error) {
// dial manually with all peers
for _, rp := range e.peerConf.Remote {
if er := e.pool.DialAndAddPeer(ctx, rp.PeerId); er != nil {
log.Info("can't dial to peer", zap.Error(er))
} else {
log.Info("connected with peer", zap.String("peerId", rp.PeerId))
}
}
go e.doRequests()
return nil
}
func (e *Example) syncHandler(ctx context.Context, msg *pool.Message) (err error) {
data := string(msg.Data) // you need unmarshal this bytes
log.Info("msg received", zap.String("peerId", msg.Peer().Id()), zap.String("data", data))
if strings.HasPrefix(data, "ack:") {
if err = msg.Ack(); err != nil {
log.Error("ack error", zap.Error(err))
}
} else if strings.HasPrefix(data, "ackErr:") {
if err = msg.AckError(42, "ack error description"); err != nil {
log.Error("ackErr error", zap.Error(err))
}
} else if strings.HasPrefix(data, "reply:") {
if err = msg.Reply([]byte("reply for:" + strings.TrimPrefix(data, "reply:"))); err != nil {
log.Error("reply error", zap.Error(err))
}
}
return nil
}
func (e *Example) doRequests() {
time.Sleep(time.Second)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
st := time.Now()
err := e.pool.SendAndWait(ctx, e.peerConf.Remote[0].PeerId, &syncproto.Message{
Header: &syncproto.Header{Type: syncproto.MessageType_MessageTypeSync},
Data: []byte("ack: something"),
})
log.Info("sent with ack:", zap.Error(err), zap.Duration("dur", time.Since(st)))
}
func (e *Example) Close(ctx context.Context) (err error) {
return
}

View File

@ -0,0 +1,104 @@
package dialer
import (
"context"
"errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/rpc"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/secure"
"github.com/libp2p/go-libp2p-core/sec"
"go.uber.org/zap"
"net"
"storj.io/drpc"
"storj.io/drpc/drpcconn"
"sync"
)
const CName = "net/dialer"
var ErrArrdsNotFound = errors.New("addrs for peer not found")
var log = logger.NewNamed(CName)
func New() Dialer {
return &dialer{}
}
type Dialer interface {
Dial(ctx context.Context, peerId string) (peer peer.Peer, err error)
UpdateAddrs(addrs map[string][]string)
app.Component
}
type dialer struct {
transport secure.Service
peerAddrs map[string][]string
mu sync.RWMutex
}
func (d *dialer) Init(ctx context.Context, a *app.App) (err error) {
d.transport = a.MustComponent(secure.CName).(secure.Service)
nodes := a.MustComponent(config.CName).(*config.Config).Nodes
d.peerAddrs = map[string][]string{}
for _, n := range nodes {
d.peerAddrs[n.PeerId] = []string{n.Address}
}
return
}
func (d *dialer) Name() (name string) {
return CName
}
func (d *dialer) UpdateAddrs(addrs map[string][]string) {
d.mu.Lock()
d.peerAddrs = addrs
d.mu.Unlock()
}
func (d *dialer) Dial(ctx context.Context, peerId string) (peer peer.Peer, err error) {
d.mu.RLock()
defer d.mu.RUnlock()
addrs, ok := d.peerAddrs[peerId]
if !ok || len(addrs) == 0 {
return nil, ErrArrdsNotFound
}
var (
stream drpc.Stream
sc sec.SecureConn
)
for _, addr := range addrs {
stream, sc, err = d.makeStream(ctx, addr)
if err != nil {
log.Info("can't connect to host", zap.String("addr", addr))
} else {
err = nil
break
}
}
if err != nil {
return
}
return rpc.PeerFromStream(sc, stream, false), nil
}
func (d *dialer) makeStream(ctx context.Context, addr string) (stream drpc.Stream, sc sec.SecureConn, err error) {
tcpConn, err := net.Dial("tcp", addr)
if err != nil {
return
}
sc, err = d.transport.TLSConn(ctx, tcpConn)
if err != nil {
return
}
log.Info("connected with remote host", zap.String("serverPeer", sc.RemotePeer().String()), zap.String("per", sc.LocalPeer().String()))
stream, err = drpcconn.New(sc).NewStream(ctx, "", rpc.Encoding)
if err != nil {
return
}
return stream, sc, err
}

35
service/net/peer/peer.go Normal file
View File

@ -0,0 +1,35 @@
package peer
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"time"
)
type Dir uint
const (
// DirInbound indicates peer created connection
DirInbound Dir = iota
// DirOutbound indicates that our host created connection
DirOutbound
)
type Info struct {
Id string
Dir Dir
LastActiveUnix int64
}
func (i Info) LastActive() time.Time {
return time.Unix(i.LastActiveUnix, 0)
}
type Peer interface {
Id() string
Info() Info
Recv() (*syncproto.Message, error)
Send(msg *syncproto.Message) (err error)
Context() context.Context
Close() error
}

View File

@ -0,0 +1,73 @@
package pool
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"go.uber.org/zap"
"gopkg.in/mgo.v2/bson"
)
type Message struct {
*syncproto.Message
peer peer.Peer
}
func (m *Message) Peer() peer.Peer {
return m.peer
}
func (m *Message) Reply(data []byte) (err error) {
rep := &syncproto.Message{
Header: &syncproto.Header{
TraceId: m.GetHeader().TraceId,
ReplyId: m.GetHeader().RequestId,
Type: syncproto.MessageType_MessageTypeSync,
},
Data: data,
}
return m.peer.Send(rep)
}
func (m *Message) Ack() (err error) {
ack := &syncproto.System{
Ack: &syncproto.SystemAck{},
}
data, err := ack.Marshal()
if err != nil {
return
}
rep := &syncproto.Message{
Header: &syncproto.Header{
TraceId: m.GetHeader().TraceId,
ReplyId: m.GetHeader().RequestId,
Type: syncproto.MessageType_MessageTypeSystem,
},
Data: data,
}
log.With(zap.String("header", rep.Header.String())).Info("sending ack to peer")
return m.peer.Send(rep)
}
func (m *Message) AckError(code syncproto.SystemErrorCode, description string) (err error) {
ack := &syncproto.System{
Ack: &syncproto.SystemAck{
Error: &syncproto.SystemError{
Code: code,
Description: description,
},
},
}
data, err := ack.Marshal()
if err != nil {
return
}
rep := &syncproto.Message{
Header: &syncproto.Header{
TraceId: []byte(bson.NewObjectId()),
ReplyId: m.GetHeader().RequestId,
Type: syncproto.MessageType_MessageTypeSystem,
},
Data: data,
}
return m.peer.Send(rep)
}

28
service/net/pool/peer.go Normal file
View File

@ -0,0 +1,28 @@
package pool
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
)
type peerEntry struct {
peer peer.Peer
groupIds []string
ready chan struct{}
}
func (pe *peerEntry) addGroup(groupId string) (ok bool) {
if slice.FindPos(pe.groupIds, groupId) != -1 {
return false
}
pe.groupIds = append(pe.groupIds, groupId)
return true
}
func (pe *peerEntry) removeGroup(groupId string) (ok bool) {
if slice.FindPos(pe.groupIds, groupId) == -1 {
return false
}
pe.groupIds = slice.Remove(pe.groupIds, groupId)
return true
}

329
service/net/pool/pool.go Normal file
View File

@ -0,0 +1,329 @@
package pool
import (
"context"
"errors"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/dialer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"go.uber.org/zap"
"sync"
"sync/atomic"
)
const (
CName = "sync/peerPool"
maxSimultaneousOperationsPerStream = 10
)
var log = logger.NewNamed("peerPool")
var (
ErrPoolClosed = errors.New("peer pool is closed")
ErrPeerNotFound = errors.New("peer not found")
)
func NewPool() Pool {
return &pool{closed: true}
}
type Handler func(ctx context.Context, msg *Message) (err error)
type Pool interface {
DialAndAddPeer(ctx context.Context, id string) (err error)
AddAndReadPeer(peer peer.Peer) (err error)
AddHandler(msgType syncproto.MessageType, h Handler)
AddPeerIdToGroup(peerId, groupId string) (err error)
RemovePeerIdFromGroup(peerId, groupId string) (err error)
SendAndWait(ctx context.Context, peerId string, msg *syncproto.Message) (err error)
Broadcast(ctx context.Context, groupId string, msg *syncproto.Message) (err error)
app.ComponentRunnable
}
type pool struct {
peersById map[string]*peerEntry
waiters *waiters
handlers map[syncproto.MessageType][]Handler
peersIdsByGroup map[string][]string
dialer dialer.Dialer
closed bool
mu sync.RWMutex
wg *sync.WaitGroup
}
func (p *pool) Init(ctx context.Context, a *app.App) (err error) {
p.peersById = map[string]*peerEntry{}
p.handlers = map[syncproto.MessageType][]Handler{}
p.peersIdsByGroup = map[string][]string{}
p.waiters = &waiters{waiters: map[uint64]*waiter{}}
p.dialer = a.MustComponent(dialer.CName).(dialer.Dialer)
p.wg = &sync.WaitGroup{}
return nil
}
func (p *pool) Name() (name string) {
return CName
}
func (p *pool) Run(ctx context.Context) (err error) {
p.closed = false
return nil
}
func (p *pool) AddHandler(msgType syncproto.MessageType, h Handler) {
p.mu.Lock()
defer p.mu.Unlock()
if !p.closed {
// unable to add handler after Run
return
}
p.handlers[msgType] = append(p.handlers[msgType], h)
}
func (p *pool) DialAndAddPeer(ctx context.Context, peerId string) (err error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.closed {
return ErrPoolClosed
}
if _, ok := p.peersById[peerId]; ok {
return nil
}
peer, err := p.dialer.Dial(ctx, peerId)
if err != nil {
return
}
p.peersById[peer.Id()] = &peerEntry{
peer: peer,
}
p.wg.Add(1)
go p.readPeerLoop(peer)
return nil
}
func (p *pool) AddAndReadPeer(peer peer.Peer) (err error) {
p.mu.Lock()
if p.closed {
p.mu.Unlock()
return ErrPoolClosed
}
p.peersById[peer.Id()] = &peerEntry{
peer: peer,
}
p.wg.Add(1)
p.mu.Unlock()
return p.readPeerLoop(peer)
}
func (p *pool) AddPeerIdToGroup(peerId, groupId string) (err error) {
p.mu.Lock()
defer p.mu.Unlock()
peer, ok := p.peersById[peerId]
if !ok {
return ErrPeerNotFound
}
if slice.FindPos(peer.groupIds, groupId) != -1 {
return nil
}
peer.addGroup(groupId)
p.peersIdsByGroup[groupId] = append(p.peersIdsByGroup[groupId], peerId)
return
}
func (p *pool) RemovePeerIdFromGroup(peerId, groupId string) (err error) {
p.mu.Lock()
defer p.mu.Unlock()
peer, ok := p.peersById[peerId]
if !ok {
return ErrPeerNotFound
}
if slice.FindPos(peer.groupIds, groupId) == -1 {
return nil
}
peer.removeGroup(groupId)
p.peersIdsByGroup[groupId] = slice.Remove(p.peersIdsByGroup[groupId], peerId)
return
}
func (p *pool) SendAndWait(ctx context.Context, peerId string, msg *syncproto.Message) (err error) {
p.mu.RLock()
peer := p.peersById[peerId]
p.mu.RUnlock()
if peer == nil {
return ErrPeerNotFound
}
repId := p.waiters.NewReplyId()
msg.GetHeader().RequestId = repId
ch := make(chan Reply, 1)
log.With(zap.Uint64("reply id", repId)).Debug("adding waiter for reply id")
p.waiters.Add(repId, &waiter{ch: ch})
defer p.waiters.Remove(repId)
if err = peer.peer.Send(msg); err != nil {
return
}
select {
case rep := <-ch:
if rep.Error != nil {
return rep.Error
}
return nil
case <-ctx.Done():
log.Debug("context error happened in send and wait")
return ctx.Err()
}
}
func (p *pool) Broadcast(ctx context.Context, groupId string, msg *syncproto.Message) (err error) {
//TODO implement me
panic("implement me")
}
func (p *pool) readPeerLoop(peer peer.Peer) (err error) {
defer p.wg.Done()
limiter := make(chan struct{}, maxSimultaneousOperationsPerStream)
for i := 0; i < maxSimultaneousOperationsPerStream; i++ {
limiter <- struct{}{}
}
Loop:
for {
msg, err := peer.Recv()
if err != nil {
log.Debug("peer receive error", zap.Error(err), zap.String("peerId", peer.Id()))
break
}
select {
case <-limiter:
case <-peer.Context().Done():
break Loop
}
go func() {
defer func() {
limiter <- struct{}{}
}()
p.handleMessage(peer, msg)
}()
}
if err = p.removePeer(peer.Id()); err != nil {
log.Error("remove peer error", zap.String("peerId", peer.Id()))
}
return
}
func (p *pool) removePeer(peerId string) (err error) {
p.mu.Lock()
defer p.mu.Unlock()
_, ok := p.peersById[peerId]
if !ok {
return ErrPeerNotFound
}
delete(p.peersById, peerId)
return
}
func (p *pool) handleMessage(peer peer.Peer, msg *syncproto.Message) {
log.With(zap.String("peerId", peer.Id()), zap.String("header", msg.GetHeader().String())).
Debug("received message from peer")
replyId := msg.GetHeader().GetReplyId()
if replyId != 0 {
if !p.waiters.Send(replyId, Reply{
PeerInfo: peer.Info(),
Message: &Message{
Message: msg,
peer: peer,
},
}) {
log.Debug("received reply with unknown (or expired) replyId", zap.Uint64("replyId", replyId), zap.String("header", msg.GetHeader().String()))
}
return
}
handlers := p.handlers[msg.GetHeader().GetType()]
if len(handlers) == 0 {
log.With(zap.String("peerId", peer.Id())).Debug("no handlers for such message")
return
}
message := &Message{Message: msg, peer: peer}
for _, h := range handlers {
if err := h(peer.Context(), message); err != nil {
log.Error("handle message error", zap.Error(err))
}
}
}
func (p *pool) Close(ctx context.Context) (err error) {
p.mu.Lock()
for _, peer := range p.peersById {
peer.peer.Close()
}
wg := p.wg
p.mu.Unlock()
if wg != nil {
wg.Wait()
}
return nil
}
type waiter struct {
sent int
ch chan<- Reply
}
type waiters struct {
waiters map[uint64]*waiter
replySeq uint64
mu sync.Mutex
}
func (w *waiters) Send(replyId uint64, r Reply) (ok bool) {
w.mu.Lock()
wait := w.waiters[replyId]
if wait == nil {
w.mu.Unlock()
return false
}
wait.sent++
var lastMessage = wait.sent == cap(wait.ch)
if lastMessage {
delete(w.waiters, replyId)
}
w.mu.Unlock()
wait.ch <- r
if lastMessage {
close(wait.ch)
}
return true
}
func (w *waiters) Add(replyId uint64, wait *waiter) {
w.mu.Lock()
w.waiters[replyId] = wait
w.mu.Unlock()
}
func (w *waiters) Remove(id uint64) error {
w.mu.Lock()
defer w.mu.Unlock()
if _, ok := w.waiters[id]; ok {
delete(w.waiters, id)
return nil
}
return fmt.Errorf("waiter not found")
}
func (w *waiters) NewReplyId() uint64 {
res := atomic.AddUint64(&w.replySeq, 1)
if res == 0 {
return w.NewReplyId()
}
return res
}

View File

@ -0,0 +1,45 @@
package pool
import "context"
// 1. message for one peerId with ack
// pool.SendAndWait(ctx context,.C
// 2. message for many peers without ack (or group)
type Request struct {
groupId string
oneOf []string
all []string
tryDial bool
needReply bool
pool *pool
}
func (r *Request) GroupId(groupId string) *Request {
r.groupId = groupId
return r
}
func (r *Request) All(peerIds ...string) *Request {
r.all = peerIds
return r
}
func (r *Request) OneOf(peerIds ...string) *Request {
r.oneOf = peerIds
return r
}
func (r *Request) TryDial(is bool) *Request {
r.tryDial = is
return r
}
func (r *Request) NeedReply(is bool) *Request {
r.needReply = is
return r
}
func (r *Request) Exec(ctx context.Context, msg *Message) *Results {
return nil
}

View File

@ -0,0 +1,53 @@
package pool
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
)
// Results of request collects replies and errors
// Must be closed after usage r.Close()
type Results struct {
ctx context.Context
cancel func()
waiterId uint64
ch chan Reply
pool *pool
}
// Iterate iterates over replies
// if callback will return a non-nil error then iteration stops
func (r *Results) Iterate(callback func(r Reply) (err error)) (err error) {
if r.ctx == nil || r.ch == nil {
return fmt.Errorf("results not initialized")
}
for {
select {
case <-r.ctx.Done():
return r.ctx.Err()
case m, ok := <-r.ch:
if ok {
if err = callback(m); err != nil {
return err
}
} else {
return
}
}
}
}
// Close cancels iteration and unregister reply handler in the pool
// Required to call to avoid memory leaks
func (r *Results) Close() (err error) {
r.cancel()
return r.pool.waiters.Remove(r.waiterId)
}
// Reply presents the result of request executing can be error or result message
type Reply struct {
PeerInfo peer.Info
Error error
Message *Message
}

View File

@ -0,0 +1,18 @@
package rpc
import (
"github.com/gogo/protobuf/proto"
"storj.io/drpc"
)
var Encoding = enc{}
type enc struct{}
func (e enc) Marshal(msg drpc.Message) ([]byte, error) {
return msg.(proto.Marshaler).Marshal()
}
func (e enc) Unmarshal(buf []byte, msg drpc.Message) error {
return msg.(proto.Unmarshaler).Unmarshal(buf)
}

View File

@ -0,0 +1,132 @@
package server
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/rpc"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/secure"
"go.uber.org/zap"
"net"
"storj.io/drpc"
"storj.io/drpc/drpcserver"
"strings"
"time"
)
const CName = "net/drpcserver"
var log = logger.NewNamed(CName)
func New() DRPCServer {
return &drpcServer{}
}
type DRPCServer interface {
app.ComponentRunnable
}
type drpcServer struct {
config config.GrpcServer
drpcServer *drpcserver.Server
transport secure.Service
listeners []secure.ContextListener
pool pool.Pool
cancel func()
}
func (s *drpcServer) Init(ctx context.Context, a *app.App) (err error) {
s.config = a.MustComponent(config.CName).(*config.Config).GrpcServer
s.transport = a.MustComponent(secure.CName).(secure.Service)
s.pool = a.MustComponent(pool.CName).(pool.Pool)
return nil
}
func (s *drpcServer) Name() (name string) {
return CName
}
func (s *drpcServer) Run(ctx context.Context) (err error) {
s.drpcServer = drpcserver.New(s)
ctx, s.cancel = context.WithCancel(ctx)
for _, addr := range s.config.ListenAddrs {
tcpList, err := net.Listen("tcp", addr)
if err != nil {
return err
}
tlsList := s.transport.TLSListener(tcpList)
go s.serve(ctx, tlsList)
}
return
}
func (s *drpcServer) serve(ctx context.Context, lis secure.ContextListener) {
l := log.With(zap.String("localAddr", lis.Addr().String()))
l.Info("drpc listener started")
defer func() {
l.Debug("drpc listener stopped")
}()
for {
select {
case <-ctx.Done():
return
default:
}
ctx, conn, err := lis.Accept(ctx)
if err != nil {
if isTemporary(err) {
l.Debug("listener temporary accept error", zap.Error(err))
t := time.NewTimer(500 * time.Millisecond)
select {
case <-t.C:
case <-ctx.Done():
return
}
continue
}
if _, ok := err.(secure.HandshakeError); ok {
l.Warn("listener handshake error", zap.Error(err))
continue
}
l.Error("listener accept error", zap.Error(err))
return
}
go s.serveConn(ctx, conn)
}
}
func (s *drpcServer) serveConn(ctx context.Context, conn net.Conn) {
l := log.With(zap.String("remoteAddr", conn.RemoteAddr().String())).With(zap.String("localAddr", conn.LocalAddr().String()))
l.Debug("connection opened")
if err := s.drpcServer.ServeOne(ctx, conn); err != nil {
if err == context.Canceled || strings.Contains(err.Error(), "EOF") {
l.Debug("connection closed")
} else {
l.Warn("serve connection error", zap.Error(err))
}
}
}
func (s *drpcServer) HandleRPC(stream drpc.Stream, _ string) (err error) {
ctx := stream.Context()
sc, err := secure.CtxSecureConn(ctx)
if err != nil {
return
}
log.With(zap.String("peer", sc.RemotePeer().String())).Debug("stream opened")
return s.pool.AddAndReadPeer(rpc.PeerFromStream(sc, stream, true))
}
func (s *drpcServer) Close(ctx context.Context) (err error) {
if s.cancel != nil {
s.cancel()
}
for _, l := range s.listeners {
if e := l.Close(); e != nil {
log.Warn("close listener error", zap.Error(e))
}
}
return
}

View File

@ -0,0 +1,18 @@
//go:build !windows
package server
import (
"errors"
"net"
)
// isTemporary checks if an error is temporary.
func isTemporary(err error) bool {
var nErr net.Error
if errors.As(err, &nErr) {
return nErr.Temporary()
}
return false
}

View File

@ -0,0 +1,41 @@
//go:build windows
package server
import (
"errors"
"net"
"os"
"syscall"
)
const (
_WSAEMFILE syscall.Errno = 10024
_WSAENETRESET syscall.Errno = 10052
_WSAENOBUFS syscall.Errno = 10055
)
// isTemporary checks if an error is temporary.
// see related go issue for more detail: https://go-review.googlesource.com/c/go/+/208537/
func isTemporary(err error) bool {
var nErr net.Error
if !errors.As(err, &nErr) {
return false
}
if nErr.Temporary() {
return true
}
var sErr *os.SyscallError
if errors.As(err, &sErr) {
switch sErr.Err {
case _WSAENETRESET,
_WSAEMFILE,
_WSAENOBUFS:
return true
}
}
return false
}

55
service/net/rpc/stream.go Normal file
View File

@ -0,0 +1,55 @@
package rpc
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"github.com/libp2p/go-libp2p-core/sec"
"storj.io/drpc"
"sync/atomic"
"time"
)
func PeerFromStream(sc sec.SecureConn, stream drpc.Stream, incoming bool) peer.Peer {
dp := &drpcPeer{
sc: sc,
Stream: stream,
}
dp.info.Id = sc.RemotePeer().String()
if incoming {
dp.info.Dir = peer.DirInbound
} else {
dp.info.Dir = peer.DirOutbound
}
return dp
}
type drpcPeer struct {
sc sec.SecureConn
info peer.Info
drpc.Stream
}
func (d *drpcPeer) Id() string {
return d.info.Id
}
func (d *drpcPeer) Info() peer.Info {
return d.info
}
func (d *drpcPeer) Recv() (msg *syncproto.Message, err error) {
msg = &syncproto.Message{}
if err = d.Stream.MsgRecv(msg, Encoding); err != nil {
return
}
atomic.StoreInt64(&d.info.LastActiveUnix, time.Now().Unix())
return
}
func (d *drpcPeer) Send(msg *syncproto.Message) (err error) {
if err = d.Stream.MsgSend(msg, Encoding); err != nil {
return
}
atomic.StoreInt64(&d.info.LastActiveUnix, time.Now().Unix())
return
}

View File

@ -0,0 +1,28 @@
package secure
import (
"context"
"errors"
"github.com/libp2p/go-libp2p-core/sec"
)
var (
ErrSecureConnNotFoundInContext = errors.New("secure connection not found in context")
)
type contextKey uint
const (
contextKeySecureConn contextKey = iota
)
func CtxSecureConn(ctx context.Context) (sec.SecureConn, error) {
if conn, ok := ctx.Value(contextKeySecureConn).(sec.SecureConn); ok {
return conn, nil
}
return nil, ErrSecureConnNotFoundInContext
}
func ctxWithSecureConn(ctx context.Context, conn sec.SecureConn) context.Context {
return context.WithValue(ctx, contextKeySecureConn, conn)
}

View File

@ -0,0 +1,50 @@
package secure
import (
"context"
"github.com/libp2p/go-libp2p-core/crypto"
libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls"
"net"
)
type ContextListener interface {
// Accept works like net.Listener accept but add context
Accept(ctx context.Context) (context.Context, net.Conn, error)
// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
Close() error
// Addr returns the listener's network address.
Addr() net.Addr
}
func newTLSListener(key crypto.PrivKey, lis net.Listener) ContextListener {
tr, _ := libp2ptls.New(key)
return &tlsListener{
tr: tr,
Listener: lis,
}
}
type tlsListener struct {
net.Listener
tr *libp2ptls.Transport
}
func (p *tlsListener) Accept(ctx context.Context) (context.Context, net.Conn, error) {
conn, err := p.Listener.Accept()
if err != nil {
return nil, nil, err
}
return p.upgradeConn(ctx, conn)
}
func (p *tlsListener) upgradeConn(ctx context.Context, conn net.Conn) (context.Context, net.Conn, error) {
secure, err := p.tr.SecureInbound(ctx, conn, "")
if err != nil {
return nil, nil, HandshakeError(err)
}
ctx = ctxWithSecureConn(ctx, secure)
return ctx, secure, nil
}

View File

@ -0,0 +1,90 @@
package secure
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/sec"
libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls"
"go.uber.org/zap"
"net"
)
type HandshakeError error
const CName = "net/secure"
var log = logger.NewNamed(CName)
func New() Service {
return &service{}
}
type Service interface {
TLSListener(lis net.Listener) ContextListener
TLSConn(ctx context.Context, conn net.Conn) (sec.SecureConn, error)
app.Component
}
type service struct {
key crypto.PrivKey
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
account := a.MustComponent(config.CName).(*config.Config).Account
decoder := signingkey.NewEDPrivKeyDecoder()
pkb, err := decoder.DecodeFromStringIntoBytes(account.SigningKey)
if err != nil {
return
}
if s.key, err = crypto.UnmarshalEd25519PrivateKey(pkb); err != nil {
return
}
pid, err := peer.Decode(account.PeerId)
if err != nil {
return
}
var testData = []byte("test data")
sign, err := s.key.Sign(testData)
if err != nil {
return
}
pubKey, err := pid.ExtractPublicKey()
if err != nil {
return
}
ok, err := pubKey.Verify(testData, sign)
if err != nil {
return
}
if !ok {
return fmt.Errorf("peerId and privateKey mismatched")
}
log.Info("secure service init", zap.String("peerId", account.PeerId))
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) TLSListener(lis net.Listener) ContextListener {
return newTLSListener(s.key, lis)
}
func (s *service) TLSConn(ctx context.Context, conn net.Conn) (sec.SecureConn, error) {
tr, err := libp2ptls.New(s.key)
if err != nil {
return nil, err
}
return tr.SecureOutbound(ctx, conn, "")
}

106
service/node/service.go Normal file
View File

@ -0,0 +1,106 @@
package node
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"go.uber.org/zap"
)
const CName = "NodesService"
var log = logger.NewNamed("nodesservice")
type Node struct {
Address string
PeerId string
SigningKey signingkey.PubKey
EncryptionKey encryptionkey.PubKey
SigningKeyString string
EncryptionKeyString string
}
func New() app.Component {
return &service{}
}
type Service interface {
Nodes() []*Node
}
type service struct {
nodes []*Node
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
cfg := a.MustComponent(config.CName).(*config.Config)
signDecoder := signingkey.NewEDPrivKeyDecoder()
rsaDecoder := encryptionkey.NewRSAPrivKeyDecoder()
var filteredNodes []*Node
for _, n := range cfg.Nodes {
if n.PeerId == cfg.Account.PeerId {
continue
}
node, err := nodeFromConfigNode(n, n.PeerId, signDecoder, rsaDecoder)
if err != nil {
return err
}
log.With(zap.String("node", node.PeerId)).Debug("adding peer to known nodes")
filteredNodes = append(filteredNodes, node)
}
s.nodes = filteredNodes
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
return nil
}
func (s *service) Close(ctx context.Context) (err error) {
return nil
}
func (s *service) Nodes() []*Node {
return s.nodes
}
func nodeFromConfigNode(
n config.Node,
peerId string,
privateSigningDecoder keys.Decoder,
privateEncryptionDecoder keys.Decoder) (*Node, error) {
decodedSigningKey, err := privateSigningDecoder.DecodeFromString(n.SigningKey)
if err != nil {
return nil, err
}
decodedEncryptionKey, err := privateEncryptionDecoder.DecodeFromString(n.EncryptionKey)
if err != nil {
return nil, err
}
encKeyString, err := privateEncryptionDecoder.EncodeToString(decodedEncryptionKey.(encryptionkey.PrivKey).GetPublic())
if err != nil {
return nil, err
}
signKeyString, err := privateSigningDecoder.EncodeToString(decodedSigningKey.(signingkey.PrivKey).GetPublic())
return &Node{
Address: n.Address,
PeerId: peerId,
SigningKey: decodedSigningKey.(signingkey.PrivKey).GetPublic(),
EncryptionKey: decodedEncryptionKey.(encryptionkey.PrivKey).GetPublic(),
SigningKeyString: signKeyString,
EncryptionKeyString: encKeyString,
}, nil
}

View File

@ -0,0 +1,188 @@
package document
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"github.com/gogo/protobuf/proto"
"go.uber.org/zap"
)
var CName = "DocumentService"
var log = logger.NewNamed("documentservice")
type service struct {
messageService message.Service
treeCache treecache.Service
account account.Service
// to create new documents we need to know all nodes
nodes []*node.Node
}
type Service interface {
UpdateDocument(ctx context.Context, id, text string) error
CreateDocument(ctx context.Context, text string) (string, error)
}
func New() app.Component {
return &service{}
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
s.account = a.MustComponent(account.CName).(account.Service)
s.messageService = a.MustComponent(message.CName).(message.Service)
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
nodesService := a.MustComponent(node.CName).(node.Service)
s.nodes = nodesService.Nodes()
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
return nil
}
func (s *service) Close(ctx context.Context) (err error) {
return nil
}
func (s *service) UpdateDocument(ctx context.Context, id, text string) (err error) {
var (
ch *aclpb.RawChange
header *treepb.TreeHeader
snapshotPath []string
heads []string
)
log.With(zap.String("id", id), zap.String("text", text)).
Debug("updating document")
err = s.treeCache.Do(ctx, id, func(tree acltree.ACLTree) error {
ch, err = tree.AddContent(ctx, func(builder acltree.ChangeBuilder) error {
builder.AddChangeContent(
&testchangepb.PlainTextChangeData{
Content: []*testchangepb.PlainTextChangeContent{
createAppendTextChangeContent(text),
},
})
return nil
})
if err != nil {
return err
}
id = tree.ID()
heads = tree.Heads()
header = tree.Header()
snapshotPath = tree.SnapshotPath()
return nil
})
if err != nil {
return err
}
log.With(
zap.String("id", id),
zap.Strings("heads", heads),
zap.String("header", header.String())).
Debug("document updated in the database")
return s.messageService.SendToSpace(ctx, "", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
Heads: heads,
Changes: []*aclpb.RawChange{ch},
TreeId: id,
SnapshotPath: snapshotPath,
TreeHeader: header,
}))
}
func (s *service) CreateDocument(ctx context.Context, text string) (id string, err error) {
acc := s.account.Account()
var (
ch *aclpb.RawChange
header *treepb.TreeHeader
snapshotPath []string
heads []string
)
err = s.treeCache.Create(ctx, func(builder acltree.ChangeBuilder) error {
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin)
if err != nil {
return err
}
// adding all predefined nodes to the document as admins
for _, n := range s.nodes {
err = builder.UserAdd(n.SigningKeyString, n.EncryptionKey, aclpb.ACLChange_Admin)
if err != nil {
return err
}
}
builder.AddChangeContent(createInitialChangeContent(text))
return nil
}, func(tree acltree.ACLTree) error {
id = tree.ID()
heads = tree.Heads()
header = tree.Header()
snapshotPath = tree.SnapshotPath()
ch, err = tree.Storage().GetChange(ctx, heads[0])
if err != nil {
return err
}
log.With(
zap.String("id", id),
zap.Strings("heads", heads),
zap.String("header", header.String())).
Debug("document created in the database")
return nil
})
if err != nil {
return "", err
}
log.With(zap.String("id", id), zap.String("text", text)).
Debug("creating document")
err = s.messageService.SendToSpace(ctx, "", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
Heads: heads,
Changes: []*aclpb.RawChange{ch},
TreeId: id,
SnapshotPath: snapshotPath,
TreeHeader: header,
}))
if err != nil {
return "", err
}
return id, err
}
func createInitialChangeContent(text string) proto.Marshaler {
return &testchangepb.PlainTextChangeData{
Content: []*testchangepb.PlainTextChangeContent{
createAppendTextChangeContent(text),
},
Snapshot: &testchangepb.PlainTextChangeSnapshot{Text: text},
}
}
func createAppendTextChangeContent(text string) *testchangepb.PlainTextChangeContent {
return &testchangepb.PlainTextChangeContent{
Value: &testchangepb.PlainTextChangeContentValueOfTextAppend{
TextAppend: &testchangepb.PlainTextChangeTextAppend{
Text: text,
},
},
}
}

View File

@ -0,0 +1,135 @@
package message
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/requesthandler"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"github.com/gogo/protobuf/proto"
"go.uber.org/zap"
"sync"
"time"
)
var log = logger.NewNamed("messageservice")
const CName = "MessageService"
type service struct {
nodes []*node.Node
requestHandler requesthandler.RequestHandler
pool pool.Pool
sync.RWMutex
}
func New() app.Component {
return &service{}
}
type Service interface {
SendMessage(ctx context.Context, peerId string, msg *syncproto.Sync) error
SendToSpace(ctx context.Context, spaceId string, msg *syncproto.Sync) error
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
s.requestHandler = a.MustComponent(requesthandler.CName).(requesthandler.RequestHandler)
s.nodes = a.MustComponent(node.CName).(node.Service).Nodes()
s.pool = a.MustComponent(pool.CName).(pool.Pool)
s.pool.AddHandler(syncproto.MessageType_MessageTypeSync, s.HandleMessage)
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
return nil
}
func (s *service) Close(ctx context.Context) (err error) {
return nil
}
func (s *service) HandleMessage(ctx context.Context, msg *pool.Message) (err error) {
log.With(
zap.String("peerId", msg.Peer().Id())).
Debug("handling message from peer")
err = msg.Ack()
if err != nil {
log.With(zap.String("peerId", msg.Peer().Id()), zap.Error(err)).
Error("could not ack message")
} else {
log.With(zap.String("peerId", msg.Peer().Id()), zap.Int("type", int(msg.Header.Type))).
Debug("ack returned")
}
syncMsg := &syncproto.Sync{}
err = proto.Unmarshal(msg.Data, syncMsg)
if err != nil {
return err
}
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()
return s.requestHandler.HandleSyncMessage(timeoutCtx, msg.Peer().Id(), syncMsg)
}
func (s *service) SendMessage(ctx context.Context, peerId string, msg *syncproto.Sync) error {
log.With(
zap.String("peerId", peerId),
zap.String("message", msgType(msg))).
Debug("sending message to peer")
err := s.pool.DialAndAddPeer(context.Background(), peerId)
if err != nil {
return err
}
marshalled, err := proto.Marshal(msg)
if err != nil {
return err
}
err = s.pool.SendAndWait(ctx, peerId, &syncproto.Message{
Header: &syncproto.Header{Type: syncproto.MessageType_MessageTypeSync},
Data: marshalled,
})
if err != nil {
log.With(
zap.String("peerId", peerId),
zap.String("message", msgType(msg)),
zap.Error(err)).
Debug("failed to send message to peer")
} else {
log.With(
zap.String("peerId", peerId),
zap.String("message", msgType(msg))).
Debug("message send to peer completed")
}
return err
}
func (s *service) SendToSpace(ctx context.Context, spaceId string, msg *syncproto.Sync) error {
for _, rp := range s.nodes {
s.SendMessage(ctx, rp.PeerId, msg)
}
return nil
}
func msgType(content *syncproto.Sync) string {
msg := content.GetMessage()
switch {
case msg.GetFullSyncRequest() != nil:
return "FullSyncRequest"
case msg.GetFullSyncResponse() != nil:
return "FullSyncResponse"
case msg.GetHeadUpdate() != nil:
return "HeadUpdate"
}
return "UnknownMessage"
}

View File

@ -0,0 +1,265 @@
package requesthandler
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"go.uber.org/zap"
)
type requestHandler struct {
treeCache treecache.Service
account account.Service
messageService MessageSender
}
var log = logger.NewNamed("requesthandler")
func New() app.Component {
return &requestHandler{}
}
type RequestHandler interface {
HandleSyncMessage(ctx context.Context, senderId string, request *syncproto.Sync) (err error)
}
type MessageSender interface {
SendMessage(ctx context.Context, peerId string, msg *syncproto.Sync) error
SendToSpace(ctx context.Context, spaceId string, msg *syncproto.Sync) error
}
const CName = "SyncRequestHandler"
func (r *requestHandler) Init(ctx context.Context, a *app.App) (err error) {
r.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
r.account = a.MustComponent(account.CName).(account.Service)
r.messageService = a.MustComponent("MessageService").(MessageSender)
return nil
}
func (r *requestHandler) Name() (name string) {
return CName
}
func (r *requestHandler) Run(ctx context.Context) (err error) {
return nil
}
func (r *requestHandler) Close(ctx context.Context) (err error) {
return nil
}
func (r *requestHandler) HandleSyncMessage(ctx context.Context, senderId string, content *syncproto.Sync) error {
msg := content.GetMessage()
switch {
case msg.GetFullSyncRequest() != nil:
return r.HandleFullSyncRequest(ctx, senderId, msg.GetFullSyncRequest())
case msg.GetFullSyncResponse() != nil:
return r.HandleFullSyncResponse(ctx, senderId, msg.GetFullSyncResponse())
case msg.GetHeadUpdate() != nil:
return r.HandleHeadUpdate(ctx, senderId, msg.GetHeadUpdate())
}
return nil
}
func (r *requestHandler) HandleHeadUpdate(ctx context.Context, senderId string, update *syncproto.SyncHeadUpdate) (err error) {
var (
fullRequest *syncproto.SyncFullRequest
snapshotPath []string
result acltree.AddResult
)
log.With(zap.String("peerId", senderId), zap.String("treeId", update.TreeId)).
Debug("received head update message")
err = r.treeCache.Do(ctx, update.TreeId, func(tree acltree.ACLTree) error {
// TODO: check if we already have those changes
result, err = tree.AddRawChanges(ctx, update.Changes...)
if err != nil {
return err
}
shouldFullSync := !slice.UnsortedEquals(update.Heads, tree.Heads())
snapshotPath = tree.SnapshotPath()
if shouldFullSync {
fullRequest, err = r.prepareFullSyncRequest(update.TreeId, update.TreeHeader, update.SnapshotPath, tree)
if err != nil {
return err
}
}
return nil
})
// if there are no such tree
if err == treestorage.ErrUnknownTreeId {
// TODO: maybe we can optimize this by sending the header and stuff right away, so when the tree is created we are able to add it on first request
fullRequest = &syncproto.SyncFullRequest{
TreeId: update.TreeId,
TreeHeader: update.TreeHeader,
}
}
// if we have incompatible heads, or we haven't seen the tree at all
if fullRequest != nil {
return r.messageService.SendMessage(ctx, senderId, syncproto.WrapFullRequest(fullRequest))
}
// if error or nothing has changed
if err != nil || len(result.Added) == 0 {
return err
}
// otherwise sending heads update message
newUpdate := &syncproto.SyncHeadUpdate{
Heads: result.Heads,
Changes: result.Added,
SnapshotPath: snapshotPath,
TreeId: update.TreeId,
TreeHeader: update.TreeHeader,
}
return r.messageService.SendToSpace(ctx, "", syncproto.WrapHeadUpdate(newUpdate))
}
func (r *requestHandler) HandleFullSyncRequest(ctx context.Context, senderId string, request *syncproto.SyncFullRequest) (err error) {
var (
fullResponse *syncproto.SyncFullResponse
snapshotPath []string
result acltree.AddResult
)
log.With(zap.String("peerId", senderId), zap.String("treeId", request.TreeId)).
Debug("received full sync request message")
err = r.treeCache.Do(ctx, request.TreeId, func(tree acltree.ACLTree) error {
// TODO: check if we already have those changes
// if we have non-empty request
if len(request.Heads) != 0 {
result, err = tree.AddRawChanges(ctx, request.Changes...)
if err != nil {
return err
}
}
snapshotPath = tree.SnapshotPath()
fullResponse, err = r.prepareFullSyncResponse(request.TreeId, request.SnapshotPath, request.Changes, tree)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
err = r.messageService.SendMessage(ctx, senderId, syncproto.WrapFullResponse(fullResponse))
// if error or nothing has changed
if err != nil || len(result.Added) == 0 {
return err
}
// otherwise sending heads update message
newUpdate := &syncproto.SyncHeadUpdate{
Heads: result.Heads,
Changes: result.Added,
SnapshotPath: snapshotPath,
TreeId: request.TreeId,
TreeHeader: request.TreeHeader,
}
return r.messageService.SendToSpace(ctx, "def", syncproto.WrapHeadUpdate(newUpdate))
}
func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId string, response *syncproto.SyncFullResponse) (err error) {
var (
snapshotPath []string
result acltree.AddResult
)
log.With(zap.String("peerId", senderId), zap.String("treeId", response.TreeId)).
Debug("received full sync response message")
err = r.treeCache.Do(ctx, response.TreeId, func(tree acltree.ACLTree) error {
// TODO: check if we already have those changes
result, err = tree.AddRawChanges(ctx, response.Changes...)
if err != nil {
return err
}
snapshotPath = tree.SnapshotPath()
return nil
})
// if error or nothing has changed
if (err != nil || len(result.Added) == 0) && err != treestorage.ErrUnknownTreeId {
return err
}
// if we have a new tree
if err == treestorage.ErrUnknownTreeId {
err = r.createTree(ctx, response)
if err != nil {
return err
}
}
// sending heads update message
newUpdate := &syncproto.SyncHeadUpdate{
Heads: result.Heads,
Changes: result.Added,
SnapshotPath: snapshotPath,
TreeId: response.TreeId,
}
return r.messageService.SendToSpace(ctx, "", syncproto.WrapHeadUpdate(newUpdate))
}
func (r *requestHandler) prepareFullSyncRequest(treeId string, header *treepb.TreeHeader, theirPath []string, tree acltree.ACLTree) (*syncproto.SyncFullRequest, error) {
ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath)
if err != nil {
return nil, err
}
return &syncproto.SyncFullRequest{
Heads: tree.Heads(),
Changes: ourChanges,
TreeId: treeId,
SnapshotPath: tree.SnapshotPath(),
TreeHeader: header,
}, nil
}
func (r *requestHandler) prepareFullSyncResponse(
treeId string,
theirPath []string,
theirChanges []*aclpb.RawChange,
tree acltree.ACLTree) (*syncproto.SyncFullResponse, error) {
// TODO: we can probably use the common snapshot calculated on the request step from previous peer
ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath)
if err != nil {
return nil, err
}
theirMap := make(map[string]struct{})
for _, ch := range theirChanges {
theirMap[ch.Id] = struct{}{}
}
// filtering our changes, so we will not send the same changes back
var final []*aclpb.RawChange
for _, ch := range ourChanges {
if _, exists := theirMap[ch.Id]; !exists {
final = append(final, ch)
}
}
log.With(zap.Int("len(changes)", len(final)), zap.String("id", treeId)).
Debug("sending changes for tree")
return &syncproto.SyncFullResponse{
Heads: tree.Heads(),
Changes: final,
TreeId: treeId,
SnapshotPath: tree.SnapshotPath(),
TreeHeader: tree.Header(),
}, nil
}
func (r *requestHandler) createTree(ctx context.Context, response *syncproto.SyncFullResponse) error {
return r.treeCache.Add(
ctx,
response.TreeId,
response.TreeHeader,
response.Changes,
func(tree acltree.ACLTree) error {
return nil
})
}

View File

@ -0,0 +1,111 @@
package treecache
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"go.uber.org/zap"
)
const CName = "treecache"
// TODO: add context
type ACLTreeFunc = func(tree acltree.ACLTree) error
type ChangeBuildFunc = func(builder acltree.ChangeBuilder) error
var log = logger.NewNamed("treecache")
type Service interface {
Do(ctx context.Context, treeId string, f ACLTreeFunc) error
Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error
Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error
}
type service struct {
treeProvider treestorage.Provider
account account.Service
cache ocache.OCache
}
func New() app.ComponentRunnable {
return &service{}
}
func (s *service) Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error {
acc := s.account.Account()
st, err := acltree.CreateNewTreeStorageWithACL(acc, build, s.treeProvider.CreateTreeStorage)
if err != nil {
return err
}
id, err := st.TreeID()
if err != nil {
return err
}
return s.Do(ctx, id, f)
}
func (s *service) Do(ctx context.Context, treeId string, f ACLTreeFunc) error {
log.
With(zap.String("treeId", treeId)).
Debug("requesting tree from cache to perform operation")
tree, err := s.cache.Get(ctx, treeId)
defer s.cache.Release(treeId)
if err != nil {
return err
}
aclTree := tree.(acltree.ACLTree)
aclTree.Lock()
defer aclTree.Unlock()
return f(tree.(acltree.ACLTree))
}
func (s *service) Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error {
log.
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(changes))).
Debug("adding tree with changes")
_, err := s.treeProvider.CreateTreeStorage(treeId, header, changes)
if err != nil {
return err
}
return s.Do(ctx, treeId, f)
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
s.cache = ocache.New(s.loadTree)
s.account = a.MustComponent(account.CName).(account.Service)
s.treeProvider = treestorage.NewInMemoryTreeStorageProvider()
// TODO: for test we should load some predefined keys
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
return nil
}
func (s *service) Close(ctx context.Context) (err error) {
return s.cache.Close()
}
func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) {
tree, err := s.treeProvider.TreeStorage(id)
if err != nil {
return nil, err
}
// TODO: should probably accept nil listeners
aclTree, err := acltree.BuildACLTree(tree, s.account.Account(), acltree.NoOpListener{})
return aclTree, err
}

19
syncproto/helpers.go Normal file
View File

@ -0,0 +1,19 @@
package syncproto
func WrapHeadUpdate(update *SyncHeadUpdate) *Sync {
return &Sync{Message: &SyncContentValue{
Value: &SyncContentValueValueOfHeadUpdate{HeadUpdate: update},
}}
}
func WrapFullRequest(request *SyncFullRequest) *Sync {
return &Sync{Message: &SyncContentValue{
Value: &SyncContentValueValueOfFullSyncRequest{FullSyncRequest: request},
}}
}
func WrapFullResponse(response *SyncFullResponse) *Sync {
return &Sync{Message: &SyncContentValue{
Value: &SyncContentValueValueOfFullSyncResponse{FullSyncResponse: response},
}}
}

102
syncproto/proto/sync.proto Normal file
View File

@ -0,0 +1,102 @@
syntax = "proto3";
package anytype;
option go_package = "/syncproto";
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
import "pkg/acl/treestorage/treepb/protos/tree.proto";
message Message {
Header header = 1;
bytes data = 2;
}
message Header {
bytes traceId = 1;
uint64 requestId = 2;
uint64 replyId = 3;
MessageType type = 4;
string debugInfo = 5;
}
enum MessageType {
MessageTypeSystem = 0;
MessageTypeSubscription = 1;
MessageTypeSync = 2;
}
message System {
Handshake handshake = 1;
Ping ping = 2;
Ack ack = 3;
message Handshake {
string protocolVersion = 1;
}
message Ping {
uint64 unixTime = 1;
}
message Ack {
Error error = 2;
}
message Error {
Code code = 1;
string description = 2;
enum Code {
UNKNOWN = 0;
UNSUPPORTED_PROTOCOL_VERSION = 10;
}
}
}
message Subscription {
SubscribeSpace subscribeSpace = 1;
UnsubscribeSpace unsubscribeSpace = 2;
message SubscribeSpace {
string spaceId = 1;
}
message UnsubscribeSpace {
string spaceId = 1;
}
}
message Sync {
string spaceId = 1;
ContentValue message = 2;
message ContentValue {
oneof value {
HeadUpdate headUpdate = 1;
Full.Request fullSyncRequest = 2;
Full.Response fullSyncResponse = 3;
}
}
message HeadUpdate {
repeated string heads = 1;
repeated acl.RawChange changes = 2;
string treeId = 3;
repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
}
message Full {
// here with send the request with all changes we have (we already know sender's snapshot path)
message Request {
repeated string heads = 1;
repeated acl.RawChange changes = 2;
string treeId = 3;
repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
}
message Response {
repeated string heads = 1;
repeated acl.RawChange changes = 2;
string treeId = 3;
repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
}
}
}

4345
syncproto/sync.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,14 @@ func NewEncryptionRsaPubKeyFromBytes(bytes []byte) (PubKey, error) {
return &EncryptionRsaPubKey{pubKey: *pk}, nil return &EncryptionRsaPubKey{pubKey: *pk}, nil
} }
func NewRSAPrivKeyDecoder() keys.Decoder {
return keys.NewKeyDecoder(NewEncryptionRsaPrivKeyFromBytes)
}
func NewRSAPubKeyDecoder() keys.Decoder {
return keys.NewKeyDecoder(NewEncryptionRsaPubKeyFromBytes)
}
func keyEquals(k1, k2 keys.Key) bool { func keyEquals(k1, k2 keys.Key) bool {
a, err := k1.Raw() a, err := k1.Raw()
if err != nil { if err != nil {

View File

@ -27,6 +27,10 @@ func NewSigningEd25519PubKeyFromBytes(bytes []byte) (PubKey, error) {
return UnmarshalEd25519PublicKey(bytes) return UnmarshalEd25519PublicKey(bytes)
} }
func NewSigningEd25519PrivKeyFromBytes(bytes []byte) (PrivKey, error) {
return UnmarshalEd25519PrivateKey(bytes)
}
func GenerateRandomEd25519KeyPair() (PrivKey, PubKey, error) { func GenerateRandomEd25519KeyPair() (PrivKey, PubKey, error) {
return GenerateEd25519Key(rand.Reader) return GenerateEd25519Key(rand.Reader)
} }
@ -144,9 +148,10 @@ func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
}, nil }, nil
} }
// TODO: remove this one in favor of new one
type Ed25519SigningPubKeyDecoder struct{} type Ed25519SigningPubKeyDecoder struct{}
func NewEd25519Decoder() PubKeyDecoder { func NewEd25519PubKeyDecoder() PubKeyDecoder {
return &Ed25519SigningPubKeyDecoder{} return &Ed25519SigningPubKeyDecoder{}
} }
@ -174,3 +179,11 @@ func (e *Ed25519SigningPubKeyDecoder) EncodeToString(pubkey PubKey) (string, err
} }
return strkey.Encode(0x5b, raw) return strkey.Encode(0x5b, raw)
} }
func NewEDPrivKeyDecoder() keys.Decoder {
return keys.NewKeyDecoder(NewSigningEd25519PrivKeyFromBytes)
}
func NewEDPubKeyDecoder() keys.Decoder {
return keys.NewKeyDecoder(NewSigningEd25519PubKeyFromBytes)
}

38
util/keys/decoder.go Normal file
View File

@ -0,0 +1,38 @@
package keys
import "github.com/anytypeio/go-anytype-infrastructure-experiments/util/strkey"
type keyDecoder[T Key] struct {
create func([]byte) (T, error)
}
func NewKeyDecoder[T Key](create func(bytes []byte) (T, error)) Decoder {
return &keyDecoder[T]{
create: create,
}
}
func (e *keyDecoder[T]) DecodeFromBytes(bytes []byte) (Key, error) {
return e.create(bytes)
}
func (e *keyDecoder[T]) DecodeFromString(identity string) (Key, error) {
pubKeyRaw, err := strkey.Decode(0x5b, identity)
if err != nil {
return nil, err
}
return e.DecodeFromBytes(pubKeyRaw)
}
func (e *keyDecoder[T]) DecodeFromStringIntoBytes(identity string) ([]byte, error) {
return strkey.Decode(0x5b, identity)
}
func (e *keyDecoder[T]) EncodeToString(key Key) (string, error) {
raw, err := key.Raw()
if err != nil {
return "", err
}
return strkey.Encode(0x5b, raw)
}

View File

@ -8,6 +8,13 @@ type Key interface {
Raw() ([]byte, error) Raw() ([]byte, error)
} }
type Decoder interface {
DecodeFromBytes(bytes []byte) (Key, error)
DecodeFromString(identity string) (Key, error)
DecodeFromStringIntoBytes(identity string) ([]byte, error)
EncodeToString(key Key) (string, error)
}
func KeyEquals(k1, k2 Key) bool { func KeyEquals(k1, k2 Key) bool {
a, err := k1.Raw() a, err := k1.Raw()
if err != nil { if err != nil {

21
util/peer/peer.go Normal file
View File

@ -0,0 +1,21 @@
package peer
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
)
func IDFromSigningPubKey(pubKey signingkey.PubKey) (peer.ID, error) {
rawSigning, err := pubKey.Raw()
if err != nil {
return "", err
}
libp2pKey, err := crypto.UnmarshalEd25519PublicKey(rawSigning)
if err != nil {
return "", err
}
return peer.IDFromPublicKey(libp2pKey)
}