diff --git a/Makefile b/Makefile index 29c7bc5..498779b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ WALLET_BIN := build/wallet -GOLANGCI_VERSION := v1.60.3 +golangci_version=v1.61.0 +golangci_installed_version=$(shell golangci-lint version --format short 2>/dev/null) .PHONY: demo run clean @@ -18,11 +19,13 @@ demo: clean: rm -f $(WALLET_BIN) - # Install golangci-lint lint-install: - @echo "--> Installing golangci-lint $(GOLANGCI_VERSION)" - @go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_VERSION) + @echo "--> Checking golangci-lint installation" + @if [ "$(golangci_installed_version)" != "$(golangci_version)" ]; then \ + echo "--> Installing golangci-lint $(golangci_version)"; \ + go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version); \ + fi # Run golangci-lint lint: @@ -34,4 +37,6 @@ lint: lint-fix: @echo "--> Running linter with fix" $(MAKE) lint-install - @golangci-lint run --fix \ No newline at end of file + @golangci-lint run --fix + +.PHONY: lint lint-fix lint-install \ No newline at end of file diff --git a/cmd/register/register.go b/cmd/register/register.go index 9b0e193..55c23fe 100644 --- a/cmd/register/register.go +++ b/cmd/register/register.go @@ -2,14 +2,14 @@ package register import ( // Import all provider packages here - "crypto-provider/pkg/factory" - _ "crypto-provider/pkg/provider/file" - _ "crypto-provider/pkg/provider/file/cmd" + "github.com/cosmos/crypto-provider/pkg/factory" + _ "github.com/cosmos/crypto-provider/pkg/impl/file" + _ "github.com/cosmos/crypto-provider/pkg/impl/file/cmd" // Add other providers as needed - // _ "crypto-provider/pkg/provider/someprovider" + // _ "github.com/cosmos/crypto-provider/pkg/impl/someprovider" ) // Init is a dummy function to ensure this package is imported func Init() { - _ = factory.GetFactory() + _ = factory.GetGlobalFactory() } diff --git a/cmd/root.go b/cmd/root.go index d99c51a..f8ba518 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,10 +1,10 @@ package main import ( - "crypto-provider/pkg/cli" - "crypto-provider/pkg/keyring" - "crypto-provider/pkg/wallet" "fmt" + "github.com/cosmos/crypto-provider/pkg/cli" + "github.com/cosmos/crypto-provider/pkg/keyring" + "github.com/cosmos/crypto-provider/pkg/wallet" "os" "github.com/spf13/cobra" diff --git a/demo/main.go b/demo/main.go index d8e3be4..bf790f6 100644 --- a/demo/main.go +++ b/demo/main.go @@ -1,15 +1,16 @@ package main import ( - "crypto-provider/pkg/components" - "crypto-provider/pkg/keyring" - "crypto-provider/pkg/provider/file" - "crypto-provider/pkg/wallet" "crypto/rand" "fmt" "log" "os" "path/filepath" + + "github.com/cosmos/crypto-provider/pkg/components" + "github.com/cosmos/crypto-provider/pkg/impl/file" + "github.com/cosmos/crypto-provider/pkg/keyring" + "github.com/cosmos/crypto-provider/pkg/wallet" ) const TestFile = "testdata/file_1.json" diff --git a/go.mod b/go.mod index 219096e..4a07740 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module crypto-provider +module github.com/cosmos/crypto-provider go 1.23 diff --git a/pkg/cli/doc.go b/pkg/cli/doc.go index ca7d781..ef6a24d 100644 --- a/pkg/cli/doc.go +++ b/pkg/cli/doc.go @@ -8,13 +8,13 @@ Key components: - Implements a GetRootCmd() function using the singleton pattern and sync.Once for thread-safety. - Initializes the root command and its flags. -2. Provider Commands (e.g., pkg/provider/file/cmd/command.go): +2. Provider Commands (e.g., pkg/impl/file/cmd/command.go): - Each provider package implements its own set of subcommands. - Uses an init() function to register its commands with the root command. How to add a new provider cli: -1. Create a new package for your provider (e.g., pkg/provider/newprovider/cmd/). +1. Create a new package for your provider (e.g., pkg/impl/newprovider/cmd/). 2. In this package, create a file (e.g., command.go) with the following structure: - Implement an init() function that calls GetRootCmd() and adds your provider's command. - Create a NewCommand() function that returns a cobra.Command for your provider. diff --git a/pkg/components/factory.go b/pkg/components/factory.go index 38619a4..481adca 100644 --- a/pkg/components/factory.go +++ b/pkg/components/factory.go @@ -2,6 +2,9 @@ package components import ( "encoding/json" + "fmt" + "os" + "path/filepath" ) // CryptoProviderFactory is a factory interface for creating CryptoProviders. @@ -9,12 +12,23 @@ import ( type CryptoProviderFactory interface { // Create creates a new CryptoProvider instance using the given source Create(source BuildSource) (CryptoProvider, error) + + // Save saves the CryptoProvider to the underlying storage + Save(provider CryptoProvider) error + // Type returns the type of the CryptoProvider that this factory creates Type() string + // SupportedSources returns the sources that this factory supports building CryptoProviders from SupportedSources() []string } +// CryptoProviderConfig defines the configuration structure for CryptoProvider. +type CryptoProviderConfig struct { + ProviderType string `json:"provider_type"` + Options map[string]interface{} `json:"options"` +} + type BuildSource interface { Type() string Validate() error @@ -72,3 +86,45 @@ func (m BuildSourceJson) Validate() error { // Additional validation can be added here if needed return nil } + +// BuildSourceConfig ////////////////////////////////////////////////////////////// +// is a BuildSource implementation that uses CryptoProviderConfig as source +// ///////////////////////////////////////////////////////////////////////////////// +type BuildSourceConfig struct { + Config CryptoProviderConfig +} + +func (m BuildSourceConfig) Type() string { return "config" } +func (m BuildSourceConfig) Validate() error { + // Validate the Config field + if m.Config.ProviderType == "" { + return fmt.Errorf("provider_type is required in the configuration") + } + // Additional validation can be added here if needed + return nil +} + +// BaseCryptoProviderFactory ////////////////////////////////////////////////////// + +type BaseFactory struct { + BaseDir string +} + +func (f *BaseFactory) Save(provider CryptoProvider) error { + metadata := provider.Metadata() + filename := fmt.Sprintf("%s.json", metadata.Name) + + path := filepath.Join(f.BaseDir, filename) + + // Create the directory if it doesn't exist + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + + data, err := metadata.Serialize() + if err != nil { + return fmt.Errorf("failed to marshal metadata: %w", err) + } + + return os.WriteFile(path, data, 0600) +} diff --git a/pkg/components/keys.go b/pkg/components/keys.go index b69b00d..94139df 100644 --- a/pkg/components/keys.go +++ b/pkg/components/keys.go @@ -13,3 +13,8 @@ type PrivKey[T PubKey] interface { Equals(other PrivKey[T]) bool Type() string } + +// KeyFactory defines how a CryptoProvider creates and manages its keys +type KeyFactory interface { + GenPubKeyFromString(string) (PubKey, error) +} diff --git a/pkg/components/metadata.go b/pkg/components/metadata.go index 5f30f7c..27828e5 100644 --- a/pkg/components/metadata.go +++ b/pkg/components/metadata.go @@ -6,7 +6,7 @@ import ( "github.com/Masterminds/semver/v3" - "crypto-provider/pkg/keyring" + "github.com/cosmos/crypto-provider/pkg/keyring" ) type ProviderConfig = map[string]any @@ -34,7 +34,7 @@ func FromRecord(record *keyring.Record) (*ProviderMetadata, error) { } // Validate checks if the ProviderMetadata is valid -func (pm *ProviderMetadata) Validate() error { +func (pm ProviderMetadata) Validate() error { _, err := semver.NewVersion(pm.Version) if err != nil { return fmt.Errorf("invalid version: %w", err) @@ -53,3 +53,12 @@ func (pm *ProviderMetadata) Validate() error { return nil } + +// Serialize returns a JSON serialized string of the ProviderMetadata +func (pm ProviderMetadata) Serialize() ([]byte, error) { + data, err := json.MarshalIndent(pm, "", " ") + if err != nil { + return nil, fmt.Errorf("failed to marshal metadata: %w", err) + } + return data, nil +} diff --git a/pkg/components/provider.go b/pkg/components/provider.go index 08e7ac9..be1ece0 100644 --- a/pkg/components/provider.go +++ b/pkg/components/provider.go @@ -13,4 +13,15 @@ type CryptoProvider interface { // Metadata returns metadata for the crypto provider. Metadata() ProviderMetadata + + // GetPubKey returns the public key of the provider + GetPubKey() PubKey + + // ProviderInitializer is an internal interface for keys initialization + ProviderInitializer +} + +type ProviderInitializer interface { + // InitializeKeys initializes the keys for the provider. + InitializeKeys() error } diff --git a/pkg/factory/factory.go b/pkg/factory/factory.go index 45ad008..eb0847c 100644 --- a/pkg/factory/factory.go +++ b/pkg/factory/factory.go @@ -1,9 +1,11 @@ package factory import ( - "crypto-provider/pkg/components" + "encoding/json" "fmt" "sync" + + "github.com/cosmos/crypto-provider/pkg/components" ) var ( @@ -15,7 +17,7 @@ type Factory struct { registry map[string]components.CryptoProviderFactory } -func GetFactory() *Factory { +func GetGlobalFactory() *Factory { once.Do(func() { factoryInstance = newFactory() }) @@ -39,8 +41,10 @@ func (f *Factory) RegisterFactory(factory components.CryptoProviderFactory) erro } if _, exists := f.registry[providerType]; exists { - return fmt.Errorf("provider type %s is already registered", providerType) + fmt.Printf("warning: factory for provider type '%s' already registered\n", providerType) + return nil } + f.registry[providerType] = factory return nil } @@ -52,7 +56,44 @@ func (f *Factory) CreateCryptoProvider(providerType string, source components.Bu return nil, fmt.Errorf("no factory registered for provider type: '%s'", providerType) } - return factory.Create(source) + provider, err := factory.Create(source) + if err != nil { + return nil, err + } + + // Type assert to internal interface + initializer, ok := provider.(components.ProviderInitializer) + if !ok { + return nil, fmt.Errorf("provider does not implement initializer interface") + } + + // Initialize keys using internal interface + if err := initializer.InitializeKeys(); err != nil { + return nil, fmt.Errorf("failed to initialize keys: %w. Check the implementation if InitializeKeys()", err) + } + + // Try get pubkey to check if it was initialized + pubKey := provider.GetPubKey() + if pubKey == nil { + return nil, fmt.Errorf("public key not available from provider") + } + + return provider, nil +} + +// LoadCryptoProvider loads a CryptoProvider from a raw JSON string. +func (f *Factory) LoadCryptoProvider(rawJSON string) (components.CryptoProvider, error) { + var config components.CryptoProviderConfig + if err := json.Unmarshal([]byte(rawJSON), &config); err != nil { + return nil, fmt.Errorf("failed to decode JSON: %w", err) + } + + if config.ProviderType == "" { + return nil, fmt.Errorf("provider_type is required in the configuration") + } + + source := components.BuildSourceConfig{Config: config} + return f.CreateCryptoProvider(config.ProviderType, source) } // newFactory creates a new Factory instance and initializes the registry map. diff --git a/pkg/provider/file/cmd/cli.go b/pkg/impl/file/cmd/cli.go similarity index 96% rename from pkg/provider/file/cmd/cli.go rename to pkg/impl/file/cmd/cli.go index 3bfc283..d2d4c25 100644 --- a/pkg/provider/file/cmd/cli.go +++ b/pkg/impl/file/cmd/cli.go @@ -1,8 +1,8 @@ package cmd import ( - "crypto-provider/pkg/cli" "fmt" + "github.com/cosmos/crypto-provider/pkg/cli" "github.com/spf13/cobra" ) diff --git a/pkg/provider/file/config.go b/pkg/impl/file/config.go similarity index 94% rename from pkg/provider/file/config.go rename to pkg/impl/file/config.go index 386a5ba..6ee9cbf 100644 --- a/pkg/provider/file/config.go +++ b/pkg/impl/file/config.go @@ -1,9 +1,10 @@ package file import ( - "crypto-provider/pkg/components" "encoding/json" "fmt" + + "github.com/cosmos/crypto-provider/pkg/components" ) // FileProviderConfig holds the configuration for the File Provider diff --git a/pkg/provider/file/factory.go b/pkg/impl/file/factory.go similarity index 79% rename from pkg/provider/file/factory.go rename to pkg/impl/file/factory.go index 83c52b4..e991b6c 100644 --- a/pkg/provider/file/factory.go +++ b/pkg/impl/file/factory.go @@ -1,10 +1,11 @@ package file import ( - "crypto-provider/pkg/components" - "crypto-provider/pkg/factory" "encoding/json" "fmt" + + "github.com/cosmos/crypto-provider/pkg/components" + "github.com/cosmos/crypto-provider/pkg/factory" ) // TODO: Should each provider have its own go.mod? @@ -13,11 +14,13 @@ const ( SourceMetadata = "metadata" ) -type FileProviderFactory struct{} +type FileProviderFactory struct { + components.BaseFactory +} // Register into the global factory func init() { - f := factory.GetFactory() + f := factory.GetGlobalFactory() err := f.RegisterFactory(&FileProviderFactory{}) if err != nil { // TODO err instead of panic @@ -40,7 +43,7 @@ func (f FileProviderFactory) Create(source components.BuildSource) (components.C } } -func createDefault(name string) (components.CryptoProvider, error) { +func createDefault(name string) (*FileProvider, error) { meta := components.ProviderMetadata{ Version: Version, Type: ProviderTypeFile, @@ -70,7 +73,7 @@ func createFromMetadata(metadata components.ProviderMetadata) (*FileProvider, er }, nil } -func createFromJson(jsonString string) (components.CryptoProvider, error) { +func createFromJson(jsonString string) (*FileProvider, error) { var metadata components.ProviderMetadata err := json.Unmarshal([]byte(jsonString), &metadata) if err != nil { @@ -86,3 +89,8 @@ func (FileProviderFactory) Type() string { func (f FileProviderFactory) SupportedSources() []string { return []string{SourceMetadata, "new", "mnemonic", "json"} } + +// Add this method to implement the full interface +func (f FileProviderFactory) Save(cp components.CryptoProvider) error { + return f.BaseFactory.Save(cp) +} diff --git a/pkg/provider/file/hasher/hash.go b/pkg/impl/file/hasher/hash.go similarity index 75% rename from pkg/provider/file/hasher/hash.go rename to pkg/impl/file/hasher/hash.go index cf934a4..2e2047a 100644 --- a/pkg/provider/file/hasher/hash.go +++ b/pkg/impl/file/hasher/hash.go @@ -1,6 +1,6 @@ package hasher -import "crypto-provider/pkg/components" +import "github.com/cosmos/crypto-provider/pkg/components" type FileHash struct{} diff --git a/pkg/impl/file/keys.go b/pkg/impl/file/keys.go new file mode 100644 index 0000000..5eaa711 --- /dev/null +++ b/pkg/impl/file/keys.go @@ -0,0 +1,63 @@ +package file + +import "github.com/cosmos/crypto-provider/pkg/components" + +type ( + PubKey = components.PubKey + PrivKey = components.PrivKey[components.PubKey] +) + +// dummyPubKey implements the PubKey interface +type dummyPubKey struct { + key string +} + +func (d *dummyPubKey) Bytes() []byte { + return []byte(d.key) +} + +func (d *dummyPubKey) Equals(other components.PubKey) bool { + if op, ok := other.(*dummyPubKey); ok { + return d.key == op.key + } + return false +} + +func (d *dummyPubKey) Type() string { + return "dummyPubKey" +} + +// NewPubKeyFromString creates a new PubKey instance from a string +func NewPubKeyFromString(key string) components.PubKey { + return &dummyPubKey{key: key} +} + +// Ensure dummyPrivKey implements the PrivKey interface +var _ PrivKey = (*dummyPrivKey)(nil) + +// Ensure dummyPubKey implements the PubKey interface +var _ components.PubKey = (*dummyPubKey)(nil) + +type dummyPrivKey struct { + key string +} + +func (d *dummyPrivKey) Bytes() []byte { + return []byte(d.key) +} + +func (d *dummyPrivKey) PubKey() components.PubKey { + // Create public key from private key + return NewPubKeyFromString(d.key) +} + +func (d *dummyPrivKey) Equals(other components.PrivKey[components.PubKey]) bool { + if op, ok := other.(*dummyPrivKey); ok { + return d.key == op.key + } + return false +} + +func (d *dummyPrivKey) Type() string { + return "dummyPrivKey" +} diff --git a/pkg/provider/file/provider.go b/pkg/impl/file/provider.go similarity index 67% rename from pkg/provider/file/provider.go rename to pkg/impl/file/provider.go index e407c18..ce7b159 100644 --- a/pkg/provider/file/provider.go +++ b/pkg/impl/file/provider.go @@ -1,10 +1,10 @@ package file import ( - "crypto-provider/pkg/components" - "crypto-provider/pkg/provider/file/hasher" - "crypto-provider/pkg/provider/file/signer" - "crypto-provider/pkg/provider/file/verifier" + "github.com/cosmos/crypto-provider/pkg/components" + "github.com/cosmos/crypto-provider/pkg/impl/file/hasher" + "github.com/cosmos/crypto-provider/pkg/impl/file/signer" + "github.com/cosmos/crypto-provider/pkg/impl/file/verifier" ) const ( @@ -39,3 +39,11 @@ func (fp *FileProvider) GetHasher() components.Hasher { func (fp *FileProvider) Metadata() components.ProviderMetadata { return fp.metadata } + +func (fp *FileProvider) GetPubKey() components.PubKey { + return NewPubKeyFromString(fp.metadata.PublicKey) +} + +func (fp *FileProvider) InitializeKeys() error { + return nil +} diff --git a/pkg/provider/file/signer/signer.go b/pkg/impl/file/signer/signer.go similarity index 97% rename from pkg/provider/file/signer/signer.go rename to pkg/impl/file/signer/signer.go index d933f81..357cdca 100644 --- a/pkg/provider/file/signer/signer.go +++ b/pkg/impl/file/signer/signer.go @@ -1,11 +1,11 @@ package signer import ( - "crypto-provider/pkg/components" "crypto/ed25519" "encoding/base64" "encoding/json" "fmt" + "github.com/cosmos/crypto-provider/pkg/components" "os" "path/filepath" ) diff --git a/pkg/provider/file/verifier/verifier.go b/pkg/impl/file/verifier/verifier.go similarity index 93% rename from pkg/provider/file/verifier/verifier.go rename to pkg/impl/file/verifier/verifier.go index 498719f..23eec91 100644 --- a/pkg/provider/file/verifier/verifier.go +++ b/pkg/impl/file/verifier/verifier.go @@ -1,10 +1,10 @@ package verifier import ( - "crypto-provider/pkg/components" "crypto/ed25519" "encoding/base64" "fmt" + "github.com/cosmos/crypto-provider/pkg/components" ) type FileSigVerifier struct { diff --git a/pkg/keyring/internal/input.go b/pkg/keyring/internal/input.go index 5fa2f55..503e72f 100644 --- a/pkg/keyring/internal/input.go +++ b/pkg/keyring/internal/input.go @@ -4,13 +4,13 @@ import ( "bufio" "errors" "fmt" - "github.com/bgentry/speakeasy" - "github.com/mattn/go-isatty" "io" "os" "path/filepath" "strings" + "github.com/bgentry/speakeasy" + "github.com/mattn/go-isatty" "golang.org/x/crypto/bcrypt" ) diff --git a/pkg/keyring/keyring.go b/pkg/keyring/keyring.go index 6567d6d..3e0de50 100644 --- a/pkg/keyring/keyring.go +++ b/pkg/keyring/keyring.go @@ -1,13 +1,14 @@ package keyring import ( - "crypto-provider/pkg/keyring/internal" "errors" "fmt" "io" "os" "github.com/99designs/keyring" + + "github.com/cosmos/crypto-provider/pkg/keyring/internal" ) // Backend options for Keyring @@ -18,9 +19,12 @@ const ( BackendMemory = "memory" ) -// const keyringFileDirName = "keyring-file" -// const keyringTestDirName = "keyring-test" -// const passKeyringPrefix = "cloudproxy" +//nolint:unused +const ( + keyringFileDirName = "keyring-file" + keyringTestDirName = "keyring-test" + passKeyringPrefix = "keyring-%s" +) var ( _ Keyring = &keystore{} @@ -54,7 +58,8 @@ func NewKeyring(appName, backend, rootDir string, userInput io.Reader) (Keyring, case BackendTest: db, err = keyring.Open(newTestBackendKeyringConfig(appName, rootDir)) case BackendFile: - cfg, err := newFileBackendKeyringConfig(appName, rootDir, userInput) + var cfg keyring.Config + cfg, err = newFileBackendKeyringConfig(appName, rootDir, userInput) if err != nil { return nil, err } @@ -170,15 +175,17 @@ func newTestBackendKeyringConfig(appName, dir string) keyring.Config { } // newPassBackendKeyringConfig creates a new pass backend keyring configuration. -// func newPassBackendKeyringConfig(appName, dir string) keyring.Config { -// prefix := fmt.Sprintf(passKeyringPrefix, appName) - -// return keyring.Config{ -// AllowedBackends: []keyring.BackendType{keyring.PassBackend}, -// ServiceName: appName, -// PassPrefix: prefix, -// } -// } +// +//nolint:unused +func newPassBackendKeyringConfig(appName, _ string, _ io.Reader) (keyring.Config, error) { + prefix := fmt.Sprintf(passKeyringPrefix, appName) + + return keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.PassBackend}, + ServiceName: appName, + PassPrefix: prefix, + }, nil +} // newFileBackendKeyringConfig creates a new file backend keyring configuration. func newFileBackendKeyringConfig(name, dir string, buf io.Reader) (keyring.Config, error) { diff --git a/pkg/provider/file/keys.go b/pkg/provider/file/keys.go deleted file mode 100644 index c8e2e01..0000000 --- a/pkg/provider/file/keys.go +++ /dev/null @@ -1,33 +0,0 @@ -package file - -import "crypto-provider/pkg/components" - -type ( - PubKey = components.PubKey - PrivKey = components.PrivKey[components.PubKey] -) - -// Ensure dummyPrivKey implements the PrivKey interface -var _ PrivKey = (*dummyPrivKey)(nil) - -type dummyPrivKey struct { - key string -} - -func (d *dummyPrivKey) Bytes() []byte { - return []byte(d.key) -} - -func (d *dummyPrivKey) PubKey() components.PubKey { - // Implement this based on your PubKey type - return nil -} - -func (d *dummyPrivKey) Equals(other components.PrivKey[components.PubKey]) bool { - // Implement proper comparison - return false -} - -func (d *dummyPrivKey) Type() string { - return "dummyPrivKey" -} diff --git a/pkg/wallet/wallet.go b/pkg/wallet/wallet.go index 6063aa2..6589168 100644 --- a/pkg/wallet/wallet.go +++ b/pkg/wallet/wallet.go @@ -1,14 +1,14 @@ package wallet import ( - "crypto-provider/cmd/register" "encoding/json" "fmt" "os" - "crypto-provider/pkg/components" - "crypto-provider/pkg/factory" - "crypto-provider/pkg/keyring" + "github.com/cosmos/crypto-provider/cmd/register" + "github.com/cosmos/crypto-provider/pkg/components" + "github.com/cosmos/crypto-provider/pkg/factory" + "github.com/cosmos/crypto-provider/pkg/keyring" ) // Wallet interface defines the operations that can be performed on a wallet. @@ -51,7 +51,7 @@ func NewKeyringWallet(appName, backend, rootDir string, addressFormatter compone return &KeyringWallet{ kr: kr, - factory: factory.GetFactory(), + factory: factory.GetGlobalFactory(), addressFormatter: addressFormatter, }, nil } diff --git a/testdata/file_1.json b/testdata/file_1.json new file mode 100644 index 0000000..014ad68 --- /dev/null +++ b/testdata/file_1.json @@ -0,0 +1,9 @@ +{ + "Name": "Demo_File_Provider_1", + "Type": "file", + "Version": "1.0.0", + "PublicKey": "ikbdrUbkZJXeTqLykGi+YNxq8JT9M0x+Ke95WKZNOfs=", + "Config": { + "FilePath": "testdata/key.json" + } +} diff --git a/testdata/key.json b/testdata/key.json new file mode 100644 index 0000000..b4ae29b --- /dev/null +++ b/testdata/key.json @@ -0,0 +1,6 @@ +{ + "priv_key": { + "type": "Ed25519", + "value": "8g7n4j2wR9oBpCDcOAlJ4MaX9jWXDxGRM/c7yFTCjmmKRt2tRuRkld5OovKQaL5g3GrwlP0zTH4p73lYpk05+w==" + } + } \ No newline at end of file