diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index e39244a36..f94c8e78d 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -246,7 +246,7 @@ type testMorphClient struct { batchTransferedGas []batchTransferGas } -func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { c.invokedMethods = append(c.invokedMethods, invokedMethod{ contract: contract, @@ -254,7 +254,7 @@ func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, metho method: method, args: args, }) - return nil + return 0, nil } func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 8a2336011..2317f3e98 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -30,7 +30,7 @@ func (ap *Processor) processEmit() bool { } // there is no signature collecting, so we don't need extra fee - err := ap.morphClient.Invoke(contract, 0, emitMethod) + _, err := ap.morphClient.Invoke(contract, 0, emitMethod) if err != nil { ap.log.Warn(logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 04dde80f7..ce6679969 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -40,7 +40,7 @@ type ( } morphClient interface { - Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error + Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error } diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index 255d498d3..f9af703de 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -23,7 +23,8 @@ func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) erro } func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { - return w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) + _, err := w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) + return err } func (w *netmapClientWrapper) ContractAddress() util.Uint160 { diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index c5adb71eb..f2521bd08 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -125,7 +125,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro } s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { - err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) + _, err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) if err != nil { s.log.Warn(logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), diff --git a/pkg/morph/client/balance/burn.go b/pkg/morph/client/balance/burn.go index 88a1aa8f1..4befbef45 100644 --- a/pkg/morph/client/balance/burn.go +++ b/pkg/morph/client/balance/burn.go @@ -36,5 +36,6 @@ func (c *Client) Burn(p BurnPrm) error { prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/lock.go b/pkg/morph/client/balance/lock.go index 7b270808e..a5b206799 100644 --- a/pkg/morph/client/balance/lock.go +++ b/pkg/morph/client/balance/lock.go @@ -48,5 +48,6 @@ func (c *Client) Lock(p LockPrm) error { prm.SetArgs(p.id, p.user, p.lock, p.amount, p.dueEpoch) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/mint.go b/pkg/morph/client/balance/mint.go index cda78c077..73448da31 100644 --- a/pkg/morph/client/balance/mint.go +++ b/pkg/morph/client/balance/mint.go @@ -36,5 +36,6 @@ func (c *Client) Mint(p MintPrm) error { prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 5206f69fa..08fb05289 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -39,7 +39,7 @@ func (c *Client) TransferX(p TransferPrm) error { prm.SetArgs(from, to, p.Amount, p.Details) prm.InvokePrmOptional = p.InvokePrmOptional - err = c.client.Invoke(prm) + _, err = c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", transferXMethod, err) } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 050838648..93a4176f9 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -174,8 +174,9 @@ func wrapFrostFSError(err error) error { } // Invoke invokes contract method by sending transaction into blockchain. +// Returns valid until block value. // Supported args types: int64, string, util.Uint160, []byte and bool. -func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -186,12 +187,12 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } txHash, vub, err := c.rpcActor.SendTunedCall(contract, method, nil, addFeeCheckerModifier(int64(fee)), args...) if err != nil { - return fmt.Errorf("could not invoke %s: %w", method, err) + return 0, fmt.Errorf("could not invoke %s: %w", method, err) } c.logger.Debug(logs.ClientNeoClientInvoke, @@ -200,7 +201,7 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, zap.Stringer("tx_hash", txHash.Reverse())) success = true - return nil + return vub, nil } // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index b520120d2..c6cf7aa8d 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -76,7 +76,7 @@ func (c *Client) Delete(p DeletePrm) error { prm.SetArgs(p.cnr, p.signature, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) } diff --git a/pkg/morph/client/container/eacl_set.go b/pkg/morph/client/container/eacl_set.go index 2d2ffb456..c68104593 100644 --- a/pkg/morph/client/container/eacl_set.go +++ b/pkg/morph/client/container/eacl_set.go @@ -85,7 +85,7 @@ func (c *Client) PutEACL(p PutEACLPrm) error { prm.SetArgs(p.table, p.sig, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", setEACLMethod, err) } diff --git a/pkg/morph/client/container/estimations.go b/pkg/morph/client/container/estimations.go index 6adf67476..f288c63cf 100644 --- a/pkg/morph/client/container/estimations.go +++ b/pkg/morph/client/container/estimations.go @@ -34,7 +34,7 @@ func (c *Client) StartEstimation(p StartEstimationPrm) error { prm.SetArgs(p.epoch) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err) } return nil @@ -47,7 +47,7 @@ func (c *Client) StopEstimation(p StopEstimationPrm) error { prm.SetArgs(p.epoch) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err) } return nil diff --git a/pkg/morph/client/container/load.go b/pkg/morph/client/container/load.go index dcf89f73e..b5263d7a6 100644 --- a/pkg/morph/client/container/load.go +++ b/pkg/morph/client/container/load.go @@ -41,7 +41,7 @@ func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error { prm.SetArgs(p.a.Epoch(), binCnr, p.a.Value(), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err) } diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index 5c23eb36d..ee323af00 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -116,7 +116,7 @@ func (c *Client) Put(p PutPrm) error { prm.SetMethod(method) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } diff --git a/pkg/morph/client/frostfs/bind.go b/pkg/morph/client/frostfs/bind.go index 5b15d5c7b..f7b91ddb8 100644 --- a/pkg/morph/client/frostfs/bind.go +++ b/pkg/morph/client/frostfs/bind.go @@ -41,7 +41,7 @@ func (x *Client) BindKeys(p BindKeysPrm) error { prm.SetArgs(p.scriptHash, p.keys) prm.InvokePrmOptional = p.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", bindKeysMethod, err) } @@ -62,7 +62,7 @@ func (x *Client) UnbindKeys(args UnbindKeysPrm) error { prm.SetArgs(args.scriptHash, args.keys) prm.InvokePrmOptional = args.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", unbindKeysMethod, err) } diff --git a/pkg/morph/client/frostfs/cheque.go b/pkg/morph/client/frostfs/cheque.go index e8f4f7f18..016b56f8f 100644 --- a/pkg/morph/client/frostfs/cheque.go +++ b/pkg/morph/client/frostfs/cheque.go @@ -43,7 +43,8 @@ func (x *Client) Cheque(p ChequePrm) error { prm.SetArgs(p.id, p.user, p.amount, p.lock) prm.InvokePrmOptional = p.InvokePrmOptional - return x.client.Invoke(prm) + _, err := x.client.Invoke(prm) + return err } // AlphabetUpdatePrm groups parameters of AlphabetUpdate operation. @@ -71,5 +72,6 @@ func (x *Client) AlphabetUpdate(p AlphabetUpdatePrm) error { prm.SetArgs(p.id, p.pubs) prm.InvokePrmOptional = p.InvokePrmOptional - return x.client.Invoke(prm) + _, err := x.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/frostfsid/addrm_keys.go b/pkg/morph/client/frostfsid/addrm_keys.go index cbbd05142..e9004f366 100644 --- a/pkg/morph/client/frostfsid/addrm_keys.go +++ b/pkg/morph/client/frostfsid/addrm_keys.go @@ -36,7 +36,7 @@ func (x *Client) AddKeys(p CommonBindPrm) error { prm.SetArgs(p.ownerID, p.keys) prm.InvokePrmOptional = p.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", addKeysMethod, err) } @@ -52,7 +52,7 @@ func (x *Client) RemoveKeys(args CommonBindPrm) error { prm.SetArgs(args.ownerID, args.keys) prm.InvokePrmOptional = args.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", removeKeysMethod, err) } diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 09ae09b51..21ba145d4 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -159,7 +159,8 @@ func (c *Client) SetConfig(p SetConfigPrm) error { prm.SetArgs(p.id, p.key, p.value) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } // RawNetworkParameter is a FrostFS network parameter which is transmitted but diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index 742165b9a..d6f8c56b2 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -34,7 +34,8 @@ func (c *Client) UpdateInnerRing(p UpdateIRPrm) error { prm.SetArgs(args) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } // GetInnerRingList return current IR list. diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index 7a63f14d7..5f9f1ce5c 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -17,7 +17,7 @@ func (c *Client) NewEpoch(epoch uint64, force bool) error { prm.SetArgs(epoch) prm.SetControlTX(force) - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) } return nil diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 4769c038c..0ce2d3b42 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -36,7 +36,7 @@ func (c *Client) AddPeer(p AddPeerPrm) error { prm.SetArgs(p.nodeInfo.Marshal()) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } return nil diff --git a/pkg/morph/client/netmap/update_state.go b/pkg/morph/client/netmap/update_state.go index 02967453b..a15459021 100644 --- a/pkg/morph/client/netmap/update_state.go +++ b/pkg/morph/client/netmap/update_state.go @@ -55,7 +55,7 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error { prm.SetArgs(int64(p.state), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke smart contract: %w", err) } return nil diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 0bbe526a6..ca3d37c2b 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -355,13 +355,15 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { // blockchain. Fallback tx is a `RET`. If Notary support is not enabled // it fallbacks to a simple `Invoke()`. // +// Returns valid until block value. +// // `nonce` and `vub` are used only if notary is enabled. -func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { +func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } if c.notary == nil { @@ -376,12 +378,12 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui // not expected to be signed by the current node. // // Considered to be used by non-IR nodes. -func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } if c.notary == nil { @@ -440,10 +442,11 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { func (c *Client) notaryInvokeAsCommittee(method string, nonce, vub uint32, args ...any) error { designate := c.GetDesignateHash() - return c.notaryInvoke(true, true, designate, nonce, &vub, method, args...) + _, err := c.notaryInvoke(true, true, designate, nonce, &vub, method, args...) + return err } -func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) error { +func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -452,22 +455,22 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint alphabetList, err := c.notary.alphabetSource() if err != nil { - return err + return 0, err } until, err := c.getUntilValue(vub) if err != nil { - return err + return 0, err } cosigners, err := c.notaryCosigners(invokedByAlpha, alphabetList, committee) if err != nil { - return err + return 0, err } nAct, err := notary.NewActor(c.client, cosigners, c.acc) if err != nil { - return err + return 0, err } mainH, fbH, untilActual, err := nAct.Notarize(nAct.MakeTunedCall(contract, method, nil, func(r *result.Invoke, t *transaction.Transaction) error { @@ -482,7 +485,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint }, args...)) if err != nil && !alreadyOnChainError(err) { - return err + return 0, err } c.logger.Debug(logs.ClientNotaryRequestInvoked, @@ -492,7 +495,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint zap.String("fallback_hash", fbH.StringLE())) success = true - return nil + return until, nil } func (c *Client) notaryCosignersFromTx(mainTx *transaction.Transaction, alphabetList keys.PublicKeys) ([]actor.SignerAccount, error) { diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 0531eacdf..1dea4c4b7 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -120,6 +120,10 @@ func (i *InvokePrmOptional) IsControl() bool { return i.controlTX } +type InvokeRes struct { + VUB uint32 +} + // Invoke calls Invoke method of Client with static internal script hash and fee. // Supported args types are the same as in Client. // @@ -129,7 +133,9 @@ func (i *InvokePrmOptional) IsControl() bool { // // If fee for the operation executed using specified method is customized, then StaticClient uses it. // Otherwise, default fee is used. -func (s StaticClient) Invoke(prm InvokePrm) error { +func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { + var res InvokeRes + var err error if s.tryNotary { if s.alpha { var ( @@ -146,24 +152,27 @@ func (s StaticClient) Invoke(prm InvokePrm) error { nonce, vub, err = s.client.CalculateNonceAndVUB(*prm.hash) } if err != nil { - return fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) + return InvokeRes{}, fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) } vubP = &vub } - return s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) + return res, err } - return s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...) + return res, err } - return s.client.Invoke( + res.VUB, err = s.client.Invoke( s.scScriptHash, s.fee, prm.method, prm.args..., ) + return res, err } // TestInvokePrm groups parameters of the TestInvoke operation.