diff --git a/cmd/node/node.go b/cmd/node/node.go index 089f20a9..157d29a5 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -7,6 +7,7 @@ import ( "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/account" "go.uber.org/zap" "os" "os/signal" @@ -17,9 +18,10 @@ import ( var log = logger.NewNamed("main") var ( - flagConfigFile = flag.String("c", "etc/config.yml", "path to config file") - flagVersion = flag.Bool("v", false, "show version and exit") - flagHelp = flag.Bool("h", false, "show help and exit") + flagConfigFile = flag.String("c", "etc/config.yml", "path to config file") + flagAccountFile = flag.String("a", "etc/account.yaml", "path to account file") + flagVersion = flag.Bool("v", false, "show version and exit") + flagHelp = flag.Bool("h", false, "show help and exit") ) func main() { @@ -44,8 +46,15 @@ func main() { log.Fatal("can't open config file", zap.Error(err)) } + // open account file with node's keys + acc, err := account.NewFromFile(*flagAccountFile) + if err != nil { + log.Fatal("can't open account file", zap.Error(err)) + } + // bootstrap components a.Register(conf) + a.Register(acc) Bootstrap(a) // start app diff --git a/etc/account.yaml b/etc/account.yaml new file mode 100644 index 00000000..5a9a0330 --- /dev/null +++ b/etc/account.yaml @@ -0,0 +1,2 @@ +signingKey: 3iT1Ue7xNejwKhZ4L8SJCKZw7RLaMy5Vh9fkWFD43ZDTg5kRV3zGPuKCzWL8d2k57EMrFCk39ddknzRVhVFC6fgi77iA +encryptionKey: 51HYzTYh5uokpYWp8EyPeTJRm6AYe2ZoZBPCLUzMR3kMijkKvEJ4bjGBdU3MxgHo4e3Dg1AFnapEZPMMHp4d3hyMB6469ZWHeGPUWh94jhB7WiRL9BtydyazQHqZQhfihK2qaTw9wgx4pq7XnydCrYS1SiQLVCGCitCLH79cHSXZNn3hrNYCz9Z3GQHX12hSKA55uzKyumZiwiiddDQ3Ufzs49hPhNuRU1QtyDYETGNCFafA2MyDv86KbdeXSgQFcghDz97A1KL2FsvfjpMBawok5NKKPmd2P1PR6cZXb1UTHRaMbAGpDuEjQNu74TsFbQQoBEahWYBgSy8Mg92JuaTjeGhLFDh5QsVF89Xj7qYK7T6CRTKuuJEgCyDYL9zbsqnZg7tXESGfazhcCYdUXXZVq3N11NDkEWz7SrNCdLscPKgqcFidBFRdVUqM2v8kGbeXQQCGTGSDsUi9yweB8xrpBdLRhJzJmKrN9xsUT8UeVjdBA4hKc8DKdV9oSxpkcJMMiCuL7EPYBA9uRMXzzeJw3HnZvFemv5QLqcPKc55q5oZp364xDwV86PMokVVGGCu67kuurertyFGKDWsfyRje7g9dy4o1t9D3pTuVmNH5Jjhb432kq38AEx8ndpAzvYPLpni44mBWutreYMg6ASDMYa19NkSRLrvjMHfF8uoP7VLitpyeWsx7mfjsQS5qms3xpTJRDJYjHN1ZPEYdxBCXPjofYyFExHH4kc27gejLMwhKMnTkGuEdnvaBSvJLwq6BUM3NsMMnqZcXFDMwarSbi67F8KyFspmYJ2jsJfEiAHzkSk65ZnppccxQjCAJgniMDQh9NwcuSG3n1Mt4VvW1B7sNrcWdFhTVnZFjBodarLJJfNYXeJDweZgwAs9Y1Ce1BbJQok1u31aJmY9ATnhKS2Bb3eDDf2kvG8q6DDcUiM5HHNqdMZbrt9jevNfR59B19C5j92DNAsCvcTmnWrSfPyphAWjJD5yTZRNdMYL1XaywncrhouSXUS7Crfpsm1yPnRQDYu6LB26vgnc35cLSNYqyX2oXfh3o4WyC2SPPCJ7LP5T8ff34hsKo78GZtc7mGreHuxieYCnJ3kYEW5WpVJ4TqQLTrnqzF2WL244V5pmUHQVF4q4ztzrG5edZS4Ah6Kq389UkU4Qo7srjMQ5KJnDpUAvJmdqdWJWftbqB5qMhRekHS3MXbgDrDL6JrpR2PcLLPPKhQHatPdhKnwgg7NABzTAxNqgb99LjsPFDhPDiK4BpWX7RbvjWm4WSZmozcRvJz75w2t3y4zvhBfNTgu8iZjE1bTL8wLpBrFMZesK5waspBP9N7uYaBKwRfb8VoUNoLWJtERwH592vqHKyg9B1mBHeH3YCQLu9NcS4qUsa5tSKmn24q9i9yBkoeVP1bFiDy3JxHUyQcaCwVgE2kWZApDw6w2T8FUp5ftWDCLb2ewGjj52cRNXb4pjgRuyLZdSa7wgn6SsQdhuAiTaKECmaEpZMoKFL9JRD9iTcAq1HNJBzP8hnaeF88UNdz8TBLr7d5Bnujpcr9mqQSj28JrRzxLNJQfWo6sWLao8LpaRzdP8QNUcv3SDMiLT9Vdb31iFvSesUzi6YG5XY95ceA7xJRzW \ No newline at end of file diff --git a/pkg/acl/acltree/acltree.go b/pkg/acl/acltree/acltree.go index 2b7ae436..ed14f446 100644 --- a/pkg/acl/acltree/acltree.go +++ b/pkg/acl/acltree/acltree.go @@ -36,6 +36,8 @@ type ACLTree interface { Iterate(func(change *Change) bool) IterateFrom(string, func(change *Change) bool) HasChange(string) bool + + Close() error } type aclTree struct { @@ -347,3 +349,7 @@ func (a *aclTree) Root() *Change { defer a.RUnlock() return a.fullTree.Root() } + +func (a *aclTree) Close() error { + return nil +} diff --git a/pkg/acl/acltree/acltree_test.go b/pkg/acl/acltree/acltree_test.go index 0f87c53c..f8313df4 100644 --- a/pkg/acl/acltree/acltree_test.go +++ b/pkg/acl/acltree/acltree_test.go @@ -27,7 +27,7 @@ func TestACLTree_UserJoinBuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) @@ -62,8 +62,25 @@ func TestACLTree_UserJoinUpdate_Append(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } + + // Use this for key generation + //encryptionDecoder := keys.NewKeyDecoder(func(bytes []byte) (keys.Key, error) { + // key, err := encryptionkey.NewEncryptionRsaPrivKeyFromBytes(bytes) + // return key, err + //}) + //encodedEncryptionKey, _ := encryptionDecoder.EncodeToString(keychain.EncryptionKeys["A"]) + // + //signingDecoder := keys.NewKeyDecoder(func(bytes []byte) (keys.Key, error) { + // key, err := signingkey.NewSigningEd25519PrivKeyFromBytes(bytes) + // return key, err + //}) + //encodedSigningKey, _ := signingDecoder.EncodeToString(keychain.SigningKeys["A"]) + // + //fmt.Println(encodedEncryptionKey) + //fmt.Println(encodedSigningKey) + listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) if err != nil { @@ -112,7 +129,7 @@ func TestACLTree_UserJoinUpdate_Rebuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) @@ -163,7 +180,7 @@ func TestACLTree_UserRemoveBuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) @@ -194,7 +211,7 @@ func TestACLTree_UserRemoveBeforeBuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) @@ -226,7 +243,7 @@ func TestACLTree_InvalidSnapshotBuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) @@ -257,7 +274,7 @@ func TestACLTree_ValidSnapshotBuild(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } listener := &mockListener{} tree, err := BuildACLTree(thr, accountData, listener) diff --git a/pkg/acl/acltree/acltreestorage.go b/pkg/acl/acltree/acltreestorage.go index a0e241f4..f5fe18c0 100644 --- a/pkg/acl/acltree/acltreestorage.go +++ b/pkg/acl/acltree/acltreestorage.go @@ -12,7 +12,7 @@ func BuildTreeStorageWithACL( create func(change *treestorage.RawChange) (treestorage.TreeStorage, error)) (treestorage.TreeStorage, error) { bld := newChangeBuilder() bld.Init( - newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519Decoder()), + newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519PubKeyDecoder()), &Tree{}, acc) err := build(bld) diff --git a/pkg/acl/example/plaintextdocument/document_test.go b/pkg/acl/example/plaintextdocument/document_test.go index 9f523fa7..7cabb4af 100644 --- a/pkg/acl/example/plaintextdocument/document_test.go +++ b/pkg/acl/example/plaintextdocument/document_test.go @@ -18,7 +18,7 @@ func TestDocument_NewPlainTextDocument(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text") @@ -36,7 +36,7 @@ func TestDocument_PlainTextDocument_AddText(t *testing.T) { Identity: keychain.GetIdentity("A"), SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], - Decoder: signingkey.NewEd25519Decoder(), + Decoder: signingkey.NewEd25519PubKeyDecoder(), } doc, err := NewPlainTextDocument(data, treestorage.NewInMemoryTreeStorage, "Some text") diff --git a/pkg/acl/testutils/treestoragebuilder/keychain.go b/pkg/acl/testutils/treestoragebuilder/keychain.go index 6211f66f..5635f072 100644 --- a/pkg/acl/testutils/treestoragebuilder/keychain.go +++ b/pkg/acl/testutils/treestoragebuilder/keychain.go @@ -32,7 +32,7 @@ func NewKeychain() *Keychain { GeneratedIdentities: map[string]string{}, ReadKeys: map[string]*SymKey{}, ReadKeysByHash: map[uint64]*SymKey{}, - coder: signingkey.NewEd25519Decoder(), + coder: signingkey.NewEd25519PubKeyDecoder(), } } diff --git a/pkg/acl/treestorage/provider.go b/pkg/acl/treestorage/provider.go new file mode 100644 index 00000000..bf0c074c --- /dev/null +++ b/pkg/acl/treestorage/provider.go @@ -0,0 +1,39 @@ +package treestorage + +import "fmt" + +type Provider interface { + TreeStorage(treeId string) (TreeStorage, error) + InsertTree(tree TreeStorage) error +} + +type inMemoryTreeStorageProvider struct { + trees map[string]TreeStorage +} + +func (i *inMemoryTreeStorageProvider) TreeStorage(treeId string) (TreeStorage, error) { + if tree, exists := i.trees[treeId]; exists { + return tree, nil + } + return nil, fmt.Errorf("tree with id %s doesn't exist", treeId) +} + +func (i *inMemoryTreeStorageProvider) InsertTree(tree TreeStorage) error { + if tree == nil { + return fmt.Errorf("tree should not be nil") + } + + id, err := tree.TreeID() + if err != nil { + return err + } + + i.trees[id] = tree + return nil +} + +func NewInMemoryTreeStorageProvider() Provider { + return &inMemoryTreeStorageProvider{ + trees: make(map[string]TreeStorage), + } +} diff --git a/pkg/acl/treestorage/models.go b/pkg/acl/treestorage/storage.go similarity index 100% rename from pkg/acl/treestorage/models.go rename to pkg/acl/treestorage/storage.go diff --git a/service/account/service.go b/service/account/service.go new file mode 100644 index 00000000..3363379d --- /dev/null +++ b/service/account/service.go @@ -0,0 +1,82 @@ +package account + +import ( + "context" + "github.com/anytypeio/go-anytype-infrastructure-experiments/app" + "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" + "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" + "gopkg.in/yaml.v3" + "io/ioutil" +) + +const CName = "account" + +type Service interface { + Account() *account.AccountData +} + +type service struct { + accountData *account.AccountData +} + +func (s *service) Account() *account.AccountData { + return s.accountData +} + +type StaticAccount struct { + SigningKey string `yaml:"siginingKey"` + EncryptionKey string `yaml:"encryptionKey"` +} + +func NewFromFile(path string) (app.Component, error) { + acc := &StaticAccount{} + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + if err = yaml.Unmarshal(data, acc); err != nil { + return nil, err + } + privateEncryptionDecoder := keys.NewKeyDecoder(func(bytes []byte) (keys.Key, error) { + key, err := encryptionkey.NewEncryptionRsaPrivKeyFromBytes(bytes) + return key, err + }) + privateSigningDecoder := keys.NewKeyDecoder(func(bytes []byte) (keys.Key, error) { + key, err := signingkey.NewSigningEd25519PrivKeyFromBytes(bytes) + return key, err + }) + // TODO: Convert this to new decoder + publicSigningDecoder := signingkey.NewEd25519PubKeyDecoder() + + decodedEncryptionKey, err := privateEncryptionDecoder.DecodeFromString(acc.EncryptionKey) + if err != nil { + return nil, err + } + decodedSiginingKey, err := privateSigningDecoder.DecodeFromString(acc.EncryptionKey) + if err != nil { + return nil, err + } + signKey := decodedSiginingKey.(signingkey.PrivKey) + identity, err := publicSigningDecoder.EncodeToString(signKey.GetPublic()) + if err != nil { + return nil, err + } + + accountData := &account.AccountData{ + Identity: identity, + SignKey: signKey, + EncKey: decodedEncryptionKey.(encryptionkey.PrivKey), + Decoder: signingkey.NewEd25519PubKeyDecoder(), + } + return &service{accountData: accountData}, nil +} + +func (s *service) Init(ctx context.Context, a *app.App) (err error) { + return nil +} + +func (s *service) Name() (name string) { + return CName +} diff --git a/service/treecache/service.go b/service/treecache/service.go new file mode 100644 index 00000000..620da179 --- /dev/null +++ b/service/treecache/service.go @@ -0,0 +1,44 @@ +package treecache + +import ( + "context" + "github.com/anytypeio/go-anytype-infrastructure-experiments/app" + "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/ocache" +) + +type TreeCache interface { + Do(ctx context.Context, treeId string, f func(tree acltree.ACLTree)) error +} + +type service struct { + treeProvider treestorage.Provider + cache ocache.OCache +} + +func (s *service) Init(ctx context.Context, a *app.App) (err error) { + s.cache = ocache.New() +} + +func (s *service) Name() (name string) { + //TODO implement me + panic("implement me") +} + +func (s *service) Run(ctx context.Context) (err error) { + //TODO implement me + panic("implement me") +} + +func (s *service) Close(ctx context.Context) (err error) { + return nil +} + +func (s *service) loadTree(ctx context.Context, id string) (value ocache.Object, err error) { + tree, err := s.treeProvider.TreeStorage(id) + if err != nil { + return nil, err + } + +} diff --git a/util/keys/asymmetric/signingkey/ed25519.go b/util/keys/asymmetric/signingkey/ed25519.go index 27f8650b..135b6864 100644 --- a/util/keys/asymmetric/signingkey/ed25519.go +++ b/util/keys/asymmetric/signingkey/ed25519.go @@ -27,6 +27,10 @@ func NewSigningEd25519PubKeyFromBytes(bytes []byte) (PubKey, error) { return UnmarshalEd25519PublicKey(bytes) } +func NewSigningEd25519PrivKeyFromBytes(bytes []byte) (PrivKey, error) { + return UnmarshalEd25519PrivateKey(bytes) +} + func GenerateRandomEd25519KeyPair() (PrivKey, PubKey, error) { return GenerateEd25519Key(rand.Reader) } @@ -146,7 +150,7 @@ func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) { type Ed25519SigningPubKeyDecoder struct{} -func NewEd25519Decoder() PubKeyDecoder { +func NewEd25519PubKeyDecoder() PubKeyDecoder { return &Ed25519SigningPubKeyDecoder{} } diff --git a/util/keys/decoder.go b/util/keys/decoder.go new file mode 100644 index 00000000..2a55872b --- /dev/null +++ b/util/keys/decoder.go @@ -0,0 +1,38 @@ +package keys + +import "github.com/anytypeio/go-anytype-infrastructure-experiments/util/strkey" + +type keyDecoder struct { + create func([]byte) (Key, error) +} + +func NewKeyDecoder(create func(bytes []byte) (Key, error)) Decoder { + return &keyDecoder{ + create: create, + } +} + +func (e *keyDecoder) DecodeFromBytes(bytes []byte) (Key, error) { + return e.create(bytes) +} + +func (e *keyDecoder) DecodeFromString(identity string) (Key, error) { + pubKeyRaw, err := strkey.Decode(0x5b, identity) + if err != nil { + return nil, err + } + + return e.DecodeFromBytes(pubKeyRaw) +} + +func (e *keyDecoder) DecodeFromStringIntoBytes(identity string) ([]byte, error) { + return strkey.Decode(0x5b, identity) +} + +func (e *keyDecoder) EncodeToString(key Key) (string, error) { + raw, err := key.Raw() + if err != nil { + return "", err + } + return strkey.Encode(0x5b, raw) +} diff --git a/util/keys/key.go b/util/keys/key.go index 150d0897..2170fac8 100644 --- a/util/keys/key.go +++ b/util/keys/key.go @@ -8,6 +8,13 @@ type Key interface { 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 { a, err := k1.Raw() if err != nil {