diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index de3aed660..e761a1b14 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -19,6 +19,7 @@ func initAPEManagerService(c *cfg) { c.cfgObject.cfgAccessPolicyEngine.policyContractHash) execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage, + c.cfgMorph.client, apemanager.WithLogger(c.log)) sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc) auditSvc := apemanager.NewAuditService(sigsvc, c.log, c.audit) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 5415da12a..657e22389 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -151,7 +151,7 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error } func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { - if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil { + if err := c.cfgMorph.client.WaitTxHalt(ctx, vub, tx); err != nil { return err } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 2eb4cd132..a26fdd798 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -423,7 +423,7 @@ func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient. if err != nil { return err } - return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res) + return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res.VUB, res.Hash) } type netInfo struct { diff --git a/pkg/ape/contract_storage/proxy.go b/pkg/ape/contract_storage/proxy.go index 953b91a79..8cbb1cce9 100644 --- a/pkg/ape/contract_storage/proxy.go +++ b/pkg/ape/contract_storage/proxy.go @@ -31,9 +31,7 @@ type RPCActorProvider interface { type ProxyVerificationContractStorage struct { rpcActorProvider RPCActorProvider - acc *wallet.Account - - proxyScriptHash util.Uint160 + cosigners []actor.SignerAccount policyScriptHash util.Uint160 } @@ -41,12 +39,27 @@ type ProxyVerificationContractStorage struct { var _ ProxyAdaptedContractStorage = (*ProxyVerificationContractStorage)(nil) func NewProxyVerificationContractStorage(rpcActorProvider RPCActorProvider, key *keys.PrivateKey, proxyScriptHash, policyScriptHash util.Uint160) *ProxyVerificationContractStorage { + acc := wallet.NewAccountFromPrivateKey(key) return &ProxyVerificationContractStorage{ rpcActorProvider: rpcActorProvider, - acc: wallet.NewAccountFromPrivateKey(key), - - proxyScriptHash: proxyScriptHash, + cosigners: []actor.SignerAccount{ + { + Signer: transaction.Signer{ + Account: proxyScriptHash, + Scopes: transaction.CustomContracts, + AllowedContracts: []util.Uint160{policyScriptHash}, + }, + Account: notary.FakeContractAccount(proxyScriptHash), + }, + { + Signer: transaction.Signer{ + Account: acc.Contract.ScriptHash(), + Scopes: transaction.CalledByEntry, + }, + Account: acc, + }, + }, policyScriptHash: policyScriptHash, } @@ -64,7 +77,7 @@ func (n *contractStorageActorAdapter) GetRPCInvoker() invoker.RPCInvoke { func (contractStorage *ProxyVerificationContractStorage) newContractStorageActor() (policy_morph.ContractStorageActor, error) { rpcActor := contractStorage.rpcActorProvider.GetRPCActor() - act, err := actor.New(rpcActor, cosigners(contractStorage.acc, contractStorage.proxyScriptHash, contractStorage.policyScriptHash)) + act, err := actor.New(rpcActor, contractStorage.cosigners) if err != nil { return nil, err } @@ -98,31 +111,16 @@ func (contractStorage *ProxyVerificationContractStorage) RemoveMorphRuleChain(na // ListMorphRuleChains lists morph rule chains from Policy contract using both Proxy contract and storage account as consigners. func (contractStorage *ProxyVerificationContractStorage) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) { - // contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but - // ProxyVerificationContractStorage does not manage reconnections. - contractStorageActor, err := contractStorage.newContractStorageActor() - if err != nil { - return nil, err - } - return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) + rpcActor := contractStorage.rpcActorProvider.GetRPCActor() + inv := &invokerAdapter{Invoker: invoker.New(rpcActor, nil), rpcInvoker: rpcActor} + return policy_morph.NewContractStorageReader(inv, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) } -func cosigners(acc *wallet.Account, proxyScriptHash, policyScriptHash util.Uint160) []actor.SignerAccount { - return []actor.SignerAccount{ - { - Signer: transaction.Signer{ - Account: proxyScriptHash, - Scopes: transaction.CustomContracts, - AllowedContracts: []util.Uint160{policyScriptHash}, - }, - Account: notary.FakeContractAccount(proxyScriptHash), - }, - { - Signer: transaction.Signer{ - Account: acc.Contract.ScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc, - }, - } +type invokerAdapter struct { + *invoker.Invoker + rpcInvoker invoker.RPCInvoke +} + +func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke { + return n.rpcInvoker } diff --git a/pkg/morph/client/waiter.go b/pkg/morph/client/waiter.go index 962ec1bc2..5b9d2cbe0 100644 --- a/pkg/morph/client/waiter.go +++ b/pkg/morph/client/waiter.go @@ -33,13 +33,13 @@ func (w *waiterClient) GetVersion() (*result.Version, error) { // WaitTxHalt waits until transaction with the specified hash persists on the blockchain. // It also checks execution result to finish in HALT state. -func (c *Client) WaitTxHalt(ctx context.Context, p InvokeRes) error { +func (c *Client) WaitTxHalt(ctx context.Context, vub uint32, h util.Uint256) error { w, err := waiter.NewPollingBased(&waiterClient{c: c}) if err != nil { return fmt.Errorf("create tx waiter: %w", err) } - res, err := w.WaitAny(ctx, p.VUB, p.Hash) + res, err := w.WaitAny(ctx, vub, h) if err != nil { return fmt.Errorf("wait until tx persists: %w", err) } diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index cc792e23d..9d8f665af 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -22,6 +22,7 @@ import ( policy_engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/mr-tron/base58/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" ) @@ -34,6 +35,8 @@ type cfg struct { type Service struct { cfg + waiter Waiter + cnrSrc containercore.Source contractStorage ape_contract.ProxyAdaptedContractStorage @@ -41,11 +44,17 @@ type Service struct { type Option func(*cfg) -func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedContractStorage, opts ...Option) *Service { +type Waiter interface { + WaitTxHalt(context.Context, uint32, util.Uint256) error +} + +func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedContractStorage, waiter Waiter, opts ...Option) *Service { s := &Service{ cnrSrc: cnrSrc, contractStorage: contractStorage, + + waiter: waiter, } for i := range opts { @@ -84,7 +93,7 @@ func (s *Service) validateContainerTargetRequest(cid string, pubKey *keys.Public return nil } -func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) (*apemanagerV2.AddChainResponse, error) { +func (s *Service) AddChain(ctx context.Context, req *apemanagerV2.AddChainRequest) (*apemanagerV2.AddChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -116,7 +125,11 @@ func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) return nil, fmt.Errorf("unsupported target type: %s", targetType) } - if _, _, err = s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain); err != nil { + txHash, vub, err := s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain) + if err != nil { + return nil, err + } + if err := s.waiter.WaitTxHalt(ctx, vub, txHash); err != nil { return nil, err } @@ -129,7 +142,7 @@ func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) return resp, nil } -func (s *Service) RemoveChain(_ context.Context, req *apemanagerV2.RemoveChainRequest) (*apemanagerV2.RemoveChainResponse, error) { +func (s *Service) RemoveChain(ctx context.Context, req *apemanagerV2.RemoveChainRequest) (*apemanagerV2.RemoveChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -148,7 +161,11 @@ func (s *Service) RemoveChain(_ context.Context, req *apemanagerV2.RemoveChainRe return nil, fmt.Errorf("unsupported target type: %s", targetType) } - if _, _, err = s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()); err != nil { + txHash, vub, err := s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()) + if err != nil { + return nil, err + } + if err := s.waiter.WaitTxHalt(ctx, vub, txHash); err != nil { return nil, err }