forked from TrueCloudLab/frostfs-node
[#787] morph: Return VUB for IR service calls
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
518f3baf41
commit
2393d13e4d
12 changed files with 78 additions and 41 deletions
|
@ -418,7 +418,8 @@ func (c *cfg) updateNetMapState(stateSetter func(*nmClient.UpdatePeerPrm)) error
|
||||||
prm.SetKey(c.key.PublicKey().Bytes())
|
prm.SetKey(c.key.PublicKey().Bytes())
|
||||||
stateSetter(&prm)
|
stateSetter(&prm)
|
||||||
|
|
||||||
return c.cfgNetmap.wrapper.UpdatePeerState(prm)
|
_, err := c.cfgNetmap.wrapper.UpdatePeerState(prm)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type netInfo struct {
|
type netInfo struct {
|
||||||
|
|
|
@ -399,7 +399,7 @@ func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) {
|
||||||
return c.netmap, nil
|
return c.netmap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testNetmapClient) NewEpoch(epoch uint64, force bool) error {
|
func (c *testNetmapClient) NewEpoch(epoch uint64) error {
|
||||||
c.newEpochs = append(c.newEpochs, epoch)
|
c.newEpochs = append(c.newEpochs, epoch)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ func (np *Processor) processNewEpochTick() bool {
|
||||||
nextEpoch := np.epochState.EpochCounter() + 1
|
nextEpoch := np.epochState.EpochCounter() + 1
|
||||||
np.log.Debug(logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch))
|
np.log.Debug(logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch))
|
||||||
|
|
||||||
err := np.netmapClient.NewEpoch(nextEpoch, false)
|
err := np.netmapClient.NewEpoch(nextEpoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
np.log.Error(logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err))
|
np.log.Error(logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err))
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -60,7 +60,7 @@ type (
|
||||||
EpochDuration() (uint64, error)
|
EpochDuration() (uint64, error)
|
||||||
MorphTxHeight(h util.Uint256) (res uint32, err error)
|
MorphTxHeight(h util.Uint256) (res uint32, err error)
|
||||||
NetMap() (*netmap.NetMap, error)
|
NetMap() (*netmap.NetMap, error)
|
||||||
NewEpoch(epoch uint64, force bool) error
|
NewEpoch(epoch uint64) error
|
||||||
MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error)
|
MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error)
|
||||||
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
|
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ type netmapClientWrapper struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error {
|
func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error {
|
||||||
return w.netmapClient.UpdatePeerState(p)
|
_, err := w.netmapClient.UpdatePeerState(p)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error {
|
func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error {
|
||||||
|
@ -43,8 +44,9 @@ func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) {
|
||||||
return w.netmapClient.NetMap()
|
return w.netmapClient.NetMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *netmapClientWrapper) NewEpoch(epoch uint64, force bool) error {
|
func (w *netmapClientWrapper) NewEpoch(epoch uint64) error {
|
||||||
return w.netmapClient.NewEpoch(epoch, force)
|
_, err := w.netmapClient.NewEpoch(epoch, 0, false)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) {
|
func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) {
|
||||||
|
|
|
@ -26,7 +26,8 @@ func Delete(c *Client, witness core.RemovalWitness) error {
|
||||||
prm.SetToken(tok.Marshal())
|
prm.SetToken(tok.Marshal())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Delete(prm)
|
_, err := c.Delete(prm)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletePrm groups parameters of Delete client operation.
|
// DeletePrm groups parameters of Delete client operation.
|
||||||
|
@ -62,13 +63,13 @@ func (d *DeletePrm) SetKey(key []byte) {
|
||||||
// Delete removes the container from FrostFS system
|
// Delete removes the container from FrostFS system
|
||||||
// through Container contract call.
|
// through Container contract call.
|
||||||
//
|
//
|
||||||
// Returns any error encountered that caused
|
// Returns valid until block and any error encountered that caused
|
||||||
// the removal to interrupt.
|
// the removal to interrupt.
|
||||||
//
|
//
|
||||||
// If TryNotary is provided, calls notary contract.
|
// If TryNotary is provided, calls notary contract.
|
||||||
func (c *Client) Delete(p DeletePrm) error {
|
func (c *Client) Delete(p DeletePrm) (uint32, error) {
|
||||||
if len(p.signature) == 0 && !p.IsControl() {
|
if len(p.signature) == 0 && !p.IsControl() {
|
||||||
return errNilArgument
|
return 0, errNilArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
prm := client.InvokePrm{}
|
prm := client.InvokePrm{}
|
||||||
|
@ -76,9 +77,9 @@ func (c *Client) Delete(p DeletePrm) error {
|
||||||
prm.SetArgs(p.cnr, p.signature, p.key, p.token)
|
prm.SetArgs(p.cnr, p.signature, p.key, p.token)
|
||||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
prm.InvokePrmOptional = p.InvokePrmOptional
|
||||||
|
|
||||||
_, err := c.client.Invoke(prm)
|
res, err := c.client.Invoke(prm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err)
|
return 0, fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err)
|
||||||
}
|
}
|
||||||
return nil
|
return res.VUB, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,17 @@ import (
|
||||||
// If `force` is true, this call is normally initiated by a control
|
// If `force` is true, this call is normally initiated by a control
|
||||||
// service command and uses a control notary transaction internally
|
// service command and uses a control notary transaction internally
|
||||||
// to ensure all nodes produce the same transaction with high probability.
|
// to ensure all nodes produce the same transaction with high probability.
|
||||||
func (c *Client) NewEpoch(epoch uint64, force bool) error {
|
// If vub > 0, vub will be used as valid until block value.
|
||||||
|
func (c *Client) NewEpoch(epoch uint64, vub uint32, force bool) (uint32, error) {
|
||||||
prm := client.InvokePrm{}
|
prm := client.InvokePrm{}
|
||||||
prm.SetMethod(newEpochMethod)
|
prm.SetMethod(newEpochMethod)
|
||||||
prm.SetArgs(epoch)
|
prm.SetArgs(epoch)
|
||||||
prm.SetControlTX(force)
|
prm.SetControlTX(force)
|
||||||
|
prm.SetVUB(vub)
|
||||||
|
|
||||||
if _, err := c.client.Invoke(prm); err != nil {
|
res, err := c.client.Invoke(prm)
|
||||||
return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err)
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err)
|
||||||
}
|
}
|
||||||
return nil
|
return res.VUB, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,17 +43,20 @@ func (c *Client) AddPeer(p AddPeerPrm) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForceRemovePeer marks the given peer as offline via a notary control transaction.
|
// ForceRemovePeer marks the given peer as offline via a notary control transaction.
|
||||||
func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo) error {
|
// If vub > 0, vub will be used as valid until block value.
|
||||||
|
func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo, vub uint32) (uint32, error) {
|
||||||
if !c.client.WithNotary() {
|
if !c.client.WithNotary() {
|
||||||
return fmt.Errorf("peer can be forcefully removed only in notary environment")
|
return 0, fmt.Errorf("peer can be forcefully removed only in notary environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
prm := UpdatePeerPrm{}
|
prm := UpdatePeerPrm{}
|
||||||
prm.SetKey(nodeInfo.PublicKey())
|
prm.SetKey(nodeInfo.PublicKey())
|
||||||
prm.SetControlTX(true)
|
prm.SetControlTX(true)
|
||||||
|
prm.SetVUB(vub)
|
||||||
|
|
||||||
if err := c.UpdatePeerState(prm); err != nil {
|
vub, err := c.UpdatePeerState(prm)
|
||||||
return fmt.Errorf("updating peer state: %v", err)
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("updating peer state: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return vub, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ func (u *UpdatePeerPrm) SetMaintenance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePeerState changes peer status through Netmap contract call.
|
// UpdatePeerState changes peer status through Netmap contract call.
|
||||||
func (c *Client) UpdatePeerState(p UpdatePeerPrm) error {
|
func (c *Client) UpdatePeerState(p UpdatePeerPrm) (uint32, error) {
|
||||||
method := updateStateMethod
|
method := updateStateMethod
|
||||||
|
|
||||||
if c.client.WithNotary() && c.client.IsAlpha() {
|
if c.client.WithNotary() && c.client.IsAlpha() {
|
||||||
|
@ -55,8 +55,9 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error {
|
||||||
prm.SetArgs(int64(p.state), p.key)
|
prm.SetArgs(int64(p.state), p.key)
|
||||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
prm.InvokePrmOptional = p.InvokePrmOptional
|
||||||
|
|
||||||
if _, err := c.client.Invoke(prm); err != nil {
|
res, err := c.client.Invoke(prm)
|
||||||
return fmt.Errorf("could not invoke smart contract: %w", err)
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not invoke smart contract: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return res.VUB, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,7 +378,7 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui
|
||||||
// not expected to be signed by the current node.
|
// not expected to be signed by the current node.
|
||||||
//
|
//
|
||||||
// Considered to be used by non-IR nodes.
|
// Considered to be used by non-IR nodes.
|
||||||
func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) {
|
func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (uint32, error) {
|
||||||
c.switchLock.RLock()
|
c.switchLock.RLock()
|
||||||
defer c.switchLock.RUnlock()
|
defer c.switchLock.RUnlock()
|
||||||
|
|
||||||
|
@ -390,7 +390,7 @@ func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8,
|
||||||
return c.Invoke(contract, fee, method, args...)
|
return c.Invoke(contract, fee, method, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.notaryInvoke(false, false, contract, rand.Uint32(), nil, method, args...)
|
return c.notaryInvoke(false, false, contract, rand.Uint32(), vubP, method, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotarySignAndInvokeTX signs and sends notary request that was received from
|
// NotarySignAndInvokeTX signs and sends notary request that was received from
|
||||||
|
|
|
@ -100,6 +100,8 @@ type InvokePrmOptional struct {
|
||||||
// It's only used by notary transactions and it affects only the
|
// It's only used by notary transactions and it affects only the
|
||||||
// computation of `validUntilBlock` values.
|
// computation of `validUntilBlock` values.
|
||||||
controlTX bool
|
controlTX bool
|
||||||
|
// vub is used to set custom valid until block value.
|
||||||
|
vub uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHash sets optional hash of the transaction.
|
// SetHash sets optional hash of the transaction.
|
||||||
|
@ -120,6 +122,11 @@ func (i *InvokePrmOptional) IsControl() bool {
|
||||||
return i.controlTX
|
return i.controlTX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetVUB sets valid until block value.
|
||||||
|
func (i *InvokePrmOptional) SetVUB(v uint32) {
|
||||||
|
i.vub = v
|
||||||
|
}
|
||||||
|
|
||||||
type InvokeRes struct {
|
type InvokeRes struct {
|
||||||
VUB uint32
|
VUB uint32
|
||||||
}
|
}
|
||||||
|
@ -136,11 +143,11 @@ type InvokeRes struct {
|
||||||
func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) {
|
func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) {
|
||||||
var res InvokeRes
|
var res InvokeRes
|
||||||
var err error
|
var err error
|
||||||
|
var vubP *uint32
|
||||||
if s.tryNotary {
|
if s.tryNotary {
|
||||||
if s.alpha {
|
if s.alpha {
|
||||||
var (
|
var (
|
||||||
nonce uint32 = 1
|
nonce uint32 = 1
|
||||||
vubP *uint32
|
|
||||||
vub uint32
|
vub uint32
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
@ -158,11 +165,19 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) {
|
||||||
vubP = &vub
|
vubP = &vub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prm.vub > 0 {
|
||||||
|
vubP = &prm.vub
|
||||||
|
}
|
||||||
|
|
||||||
res.VUB, err = 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 res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...)
|
if prm.vub > 0 {
|
||||||
|
vubP = &prm.vub
|
||||||
|
}
|
||||||
|
|
||||||
|
res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, vubP, prm.method, prm.args...)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,11 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c
|
||||||
return nil, fmt.Errorf("getting current epoch: %w", err)
|
return nil, fmt.Errorf("getting current epoch: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.netmapClient.NewEpoch(epoch+1, true); err != nil {
|
vub, err := s.netmapClient.NewEpoch(epoch+1, req.GetBody().GetVub(), true)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("forcing new epoch: %w", err)
|
return nil, fmt.Errorf("forcing new epoch: %w", err)
|
||||||
}
|
}
|
||||||
|
resp.Body.Vub = vub
|
||||||
|
|
||||||
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
@ -93,9 +95,11 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) (
|
||||||
return nil, status.Error(codes.FailedPrecondition, "node is already offline")
|
return nil, status.Error(codes.FailedPrecondition, "node is already offline")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.netmapClient.ForceRemovePeer(nodeInfo); err != nil {
|
vub, err := s.netmapClient.ForceRemovePeer(nodeInfo, req.GetBody().GetVub())
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("forcing node removal: %w", err)
|
return nil, fmt.Errorf("forcing node removal: %w", err)
|
||||||
}
|
}
|
||||||
|
resp.Body.Vub = vub
|
||||||
|
|
||||||
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
@ -113,13 +117,15 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer
|
||||||
if len(req.Body.GetContainerId()) > 0 && len(req.Body.GetOwner()) > 0 {
|
if len(req.Body.GetContainerId()) > 0 && len(req.Body.GetOwner()) > 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "specify the owner and container at the same time is not allowed")
|
return nil, status.Error(codes.InvalidArgument, "specify the owner and container at the same time is not allowed")
|
||||||
}
|
}
|
||||||
|
var vub uint32
|
||||||
if len(req.Body.GetContainerId()) > 0 {
|
if len(req.Body.GetContainerId()) > 0 {
|
||||||
var containerID cid.ID
|
var containerID cid.ID
|
||||||
if err := containerID.Decode(req.Body.GetContainerId()); err != nil {
|
if err := containerID.Decode(req.Body.GetContainerId()); err != nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error()))
|
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error()))
|
||||||
}
|
}
|
||||||
if err := s.removeContainer(containerID); err != nil {
|
var err error
|
||||||
|
vub, err = s.removeContainer(containerID, req.GetBody().GetVub())
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,14 +144,17 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, containerID := range cids {
|
for _, containerID := range cids {
|
||||||
if err := s.removeContainer(containerID); err != nil {
|
vub, err = s.removeContainer(containerID, req.GetBody().GetVub())
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &control.RemoveContainerResponse{
|
resp := &control.RemoveContainerResponse{
|
||||||
Body: &control.RemoveContainerResponse_Body{},
|
Body: &control.RemoveContainerResponse_Body{
|
||||||
|
Vub: vub,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
@ -153,13 +162,15 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) removeContainer(containerID cid.ID) error {
|
func (s *Server) removeContainer(containerID cid.ID, vub uint32) (uint32, error) {
|
||||||
var prm container.DeletePrm
|
var prm container.DeletePrm
|
||||||
prm.SetCID(containerID[:])
|
prm.SetCID(containerID[:])
|
||||||
prm.SetControlTX(true)
|
prm.SetControlTX(true)
|
||||||
|
prm.SetVUB(vub)
|
||||||
|
|
||||||
if err := s.containerClient.Delete(prm); err != nil {
|
vub, err := s.containerClient.Delete(prm)
|
||||||
return fmt.Errorf("forcing container removal: %w", err)
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("forcing container removal: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return vub, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue