package frostfsid import ( "context" "fmt" "strings" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-http-gw/resolver" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" ) type FrostFSID struct { cli *client.Client } type Config struct { // RPCAddress is an endpoint to connect to neo rpc. RPCAddress string // Contract is hash of contract or its name in NNS. Contract string // Key is used to interact with frostfsid contract. // If this is nil than random key will be generated. Key *keys.PrivateKey } // New creates new FrostfsID contract wrapper that implements auth.FrostFSID interface. func New(ctx context.Context, cfg Config) (*FrostFSID, error) { rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{}) if err != nil { return nil, fmt.Errorf("init rpc client: %w", err) } contractHash, err := fetchContractHash(rpcCli, cfg.Contract) if err != nil { return nil, fmt.Errorf("resolve frostfs contract hash: %w", err) } key := cfg.Key if key == nil { if key, err = keys.NewPrivateKey(); err != nil { return nil, fmt.Errorf("generate anon private key for frostfsid: %w", err) } } cli, err := client.New(rpcCli, wallet.NewAccountFromPrivateKey(key), contractHash, nil) if err != nil { return nil, fmt.Errorf("init frostfsid client: %w", err) } return &FrostFSID{ cli: cli, }, nil } func (f *FrostFSID) ValidatePublicKey(key *keys.PublicKey) error { _, err := f.cli.GetSubjectByKey(key) return err } func fetchContractHash(rpcCli *rpcclient.Client, contractName string) (util.Uint160, error) { if hash, err := util.Uint160DecodeStringLE(contractName); err == nil { return hash, nil } splitName := strings.Split(contractName, ".") if len(splitName) != 2 { return util.Uint160{}, fmt.Errorf("invalid contract name: '%s'", contractName) } return resolver.ResolveHash(rpcCli, contractName) }