diff --git a/CHANGELOG.md b/CHANGELOG.md index 89e2a28f3d..b9035b2732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Changelog for NeoFS Node - Correctly reset shard errors in `ControlService.SetShardMode` RPC (#1931) - Setting node's network state to `MAINTENANCE` while network settings forbid it (#1916) - Do not panic during API client creation (#1936) +- Correctly sign new epoch transaction in neofs-adm for a committee of more than 4 nodes (#1949) ### Removed ### Updated diff --git a/cmd/neofs-adm/internal/modules/morph/epoch.go b/cmd/neofs-adm/internal/modules/morph/epoch.go index bee048600c..cf8b82a67a 100644 --- a/cmd/neofs-adm/internal/modules/morph/epoch.go +++ b/cmd/neofs-adm/internal/modules/morph/epoch.go @@ -34,7 +34,7 @@ func forceNewEpochCmd(cmd *cobra.Command, args []string) error { return err } - if err := wCtx.sendCommitteeTx(bw.Bytes(), true); err != nil { + if err := wCtx.sendMultiTx(bw.Bytes(), true, true); err != nil { return err } diff --git a/cmd/neofs-adm/internal/modules/morph/initialize.go b/cmd/neofs-adm/internal/modules/morph/initialize.go index 348e563de9..ddc040b028 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize.go @@ -281,17 +281,17 @@ func (c *initializeContext) nnsContractState() (*state.Contract, error) { return cs, nil } -func (c *initializeContext) getSigner(tryGroup bool) transaction.Signer { +func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { if tryGroup && c.groupKey != nil { return transaction.Signer{ - Account: c.CommitteeAcc.Contract.ScriptHash(), + Account: acc.Contract.ScriptHash(), Scopes: transaction.CustomGroups, AllowedGroups: keys.PublicKeys{c.groupKey}, } } signer := transaction.Signer{ - Account: c.CommitteeAcc.Contract.ScriptHash(), + Account: acc.Contract.ScriptHash(), Scopes: transaction.Global, // Scope is important, as we have nested call to container contract. } @@ -388,15 +388,31 @@ loop: // If tryGroup is false, global scope is used for the signer (useful when // working with native contracts). func (c *initializeContext) sendCommitteeTx(script []byte, tryGroup bool) error { + return c.sendMultiTx(script, tryGroup, false) +} + +func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { var act *actor.Actor var err error if tryGroup { - act, err = actor.New(c.Client, []actor.SignerAccount{{ - Signer: c.getSigner(tryGroup), + // Even for consensus signatures we need the committee to pay. + signers := make([]actor.SignerAccount, 1, 2) + signers[0] = actor.SignerAccount{ + Signer: c.getSigner(tryGroup, c.CommitteeAcc), Account: c.CommitteeAcc, - }}) + } + if withConsensus { + signers = append(signers, actor.SignerAccount{ + Signer: c.getSigner(tryGroup, c.ConsensusAcc), + Account: c.ConsensusAcc, + }) + } + act, err = actor.New(c.Client, signers) } else { + if withConsensus { + panic("BUG: should never happen") + } act, err = c.CommitteeAct, nil } if err != nil { @@ -408,7 +424,16 @@ func (c *initializeContext) sendCommitteeTx(script []byte, tryGroup bool) error return fmt.Errorf("could not perform test invocation: %w", err) } - return c.multiSignAndSend(tx, committeeAccountName) + if err := c.multiSign(tx, committeeAccountName); err != nil { + return err + } + if withConsensus { + if err := c.multiSign(tx, consensusAccountName); err != nil { + return err + } + } + + return c.sendTx(tx, c.Command, false) } func getWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_register.go b/cmd/neofs-adm/internal/modules/morph/initialize_register.go index e9e567dedb..6b7e47d62a 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize_register.go @@ -50,7 +50,7 @@ func (c *initializeContext) registerCandidates() error { } signers := []rpcclient.SignerAccount{{ - Signer: c.getSigner(false), + Signer: c.getSigner(false, c.CommitteeAcc), Account: c.CommitteeAcc, }} for i := range c.Accounts { diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_transfer.go b/cmd/neofs-adm/internal/modules/morph/initialize_transfer.go index 09579ce81a..591f809d9f 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize_transfer.go @@ -125,7 +125,7 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin } } - w, err := pc.GetWitness(tx.Signers[0].Account) + w, err := pc.GetWitness(h) if err != nil { return fmt.Errorf("incomplete signature: %w", err) }