frostfs-s3-gw/internal/frostfs/policy/contract/contract.go
Denis Kirillov 899213b3f3
All checks were successful
/ Builds (1.20) (pull_request) Successful in 1m52s
/ Builds (1.21) (pull_request) Successful in 1m12s
/ DCO (pull_request) Successful in 1m46s
/ Vulncheck (pull_request) Successful in 1m43s
/ Lint (pull_request) Successful in 4m3s
/ Tests (1.20) (pull_request) Successful in 2m24s
/ Tests (1.21) (pull_request) Successful in 2m23s
[#287] Support proxy for frostfsid and policy contracts
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-12-22 15:45:10 +03:00

132 lines
3.8 KiB
Go

package contract
import (
"context"
"fmt"
"math/big"
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
policyclient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/policy"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy"
frostfsutil "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/notary"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
)
type Client struct {
actor *actor.Actor
policyContract *policyclient.Contract
}
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
// ProxyContract is hash of proxy contract or its name in NNS to interact with policy.
ProxyContract string
// Key is used to interact with policy contract.
// If this is nil than random key will be generated.
Key *keys.PrivateKey
}
var _ policy.Contract = (*Client)(nil)
// New creates new Policy contract wrapper.
func New(ctx context.Context, cfg Config) (*Client, error) {
contractHash, err := frostfsutil.ResolveContractHash(cfg.Contract, cfg.RPCAddress)
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 policy: %w", err)
}
}
rpcCli, err := rpcclient.New(ctx, cfg.RPCAddress, rpcclient.Options{})
if err != nil {
return nil, fmt.Errorf("create policy rpc client: %w", err)
}
proxyContractHash, err := frostfsutil.ResolveContractHash(cfg.ProxyContract, cfg.RPCAddress)
if err != nil {
return nil, fmt.Errorf("resolve frostfs contract hash: %w", err)
}
act, err := actor.New(rpcCli, getSigners(key, proxyContractHash, contractHash))
if err != nil {
return nil, fmt.Errorf("create new actor: %w", err)
}
return &Client{
actor: act,
policyContract: policyclient.New(act, contractHash),
}, nil
}
func getSigners(key *keys.PrivateKey, proxyHash, contractHash util.Uint160) []actor.SignerAccount {
acc := wallet.NewAccountFromPrivateKey(key)
return []actor.SignerAccount{
{
Signer: transaction.Signer{
Account: proxyHash,
Scopes: transaction.CustomContracts,
AllowedContracts: []util.Uint160{contractHash},
},
Account: notary.FakeContractAccount(proxyHash),
},
{
Signer: transaction.Signer{
Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry,
},
Account: acc,
},
}
}
func (c *Client) AddChain(kind policycontract.Kind, entity string, name []byte, chain []byte) (util.Uint256, uint32, error) {
return c.policyContract.AddChain(big.NewInt(int64(kind)), entity, name, chain)
}
func (c *Client) GetChain(kind policycontract.Kind, entity string, name []byte) ([]byte, error) {
return c.policyContract.GetChain(big.NewInt(int64(kind)), entity, name)
}
func (c *Client) RemoveChain(kind policycontract.Kind, entity string, name []byte) (util.Uint256, uint32, error) {
return c.policyContract.RemoveChain(big.NewInt(int64(kind)), entity, name)
}
func (c *Client) ListChains(kind policycontract.Kind, entity string, name []byte) ([][]byte, error) {
items, err := c.policyContract.ListChainsByPrefix(big.NewInt(int64(kind)), entity, name)
if err != nil {
return nil, err
}
res := make([][]byte, len(items))
for i, item := range items {
res[i], err = item.TryBytes()
if err != nil {
return nil, err
}
}
return res, nil
}
func (c *Client) Wait(tx util.Uint256, vub uint32, err error) error {
_, err = c.actor.Wait(tx, vub, err)
return err
}