2023-12-05 09:12:35 +00:00
|
|
|
package contract
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
|
|
|
|
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
|
|
|
|
policyclient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/policy"
|
2023-12-07 14:13:11 +00:00
|
|
|
frostfsutil "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
|
2023-12-05 09:12:35 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
|
|
|
"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"
|
2023-12-07 14:13:11 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2023-12-05 09:12:35 +00:00
|
|
|
"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
|
|
|
|
|
|
|
|
// Key is used to interact with policy contract.
|
|
|
|
// If this is nil than random key will be generated.
|
|
|
|
Key *keys.PrivateKey
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ engine.MorphRuleChainStorage = (*Client)(nil)
|
|
|
|
|
|
|
|
// New creates new Policy contract wrapper.
|
|
|
|
func New(ctx context.Context, cfg Config) (*Client, error) {
|
2023-12-07 14:13:11 +00:00
|
|
|
contractHash, err := frostfsutil.ResolveContractHash(cfg.Contract, cfg.RPCAddress)
|
2023-12-05 09:12:35 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
acc := wallet.NewAccountFromPrivateKey(key)
|
|
|
|
act, err := actor.NewSimple(rpcCli, acc)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("create new actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Client{
|
|
|
|
actor: act,
|
|
|
|
policyContract: policyclient.New(act, contractHash),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2023-12-07 14:13:11 +00:00
|
|
|
func (c *Client) AddMorphRuleChain(name chain.Name, target engine.Target, policyChain *chain.Chain) (util.Uint256, uint32, error) {
|
2023-12-05 09:12:35 +00:00
|
|
|
chainName := append([]byte(name), []byte(policyChain.ID)...)
|
2023-12-07 14:13:11 +00:00
|
|
|
return c.policyContract.AddChain(getKind(target), target.Name, chainName, policyChain.Bytes())
|
2023-12-05 09:12:35 +00:00
|
|
|
}
|
|
|
|
|
2023-12-07 14:13:11 +00:00
|
|
|
func (c *Client) RemoveMorphRuleChain(name chain.Name, target engine.Target, chainID chain.ID) (util.Uint256, uint32, error) {
|
2023-12-05 09:12:35 +00:00
|
|
|
chainName := append([]byte(name), []byte(chainID)...)
|
2023-12-07 14:13:11 +00:00
|
|
|
return c.policyContract.RemoveChain(getKind(target), target.Name, chainName)
|
2023-12-05 09:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) {
|
|
|
|
items, err := c.policyContract.ListChainsByPrefix(getKind(target), target.Name, []byte(name))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
res := make([]*chain.Chain, len(items))
|
|
|
|
for i, item := range items {
|
|
|
|
data, err := item.TryBytes()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var policyChain chain.Chain
|
|
|
|
if err = policyChain.DecodeBytes(data); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
res[i] = &policyChain
|
|
|
|
}
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func getKind(target engine.Target) *big.Int {
|
|
|
|
var kind int64 = policycontract.Container
|
|
|
|
if target.Type != engine.Container {
|
|
|
|
kind = policycontract.Namespace
|
|
|
|
}
|
|
|
|
|
|
|
|
return big.NewInt(kind)
|
|
|
|
}
|