From e3c0288e504ab80b34b5608c0116bb224574a1c7 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Thu, 23 Sep 2021 19:56:13 +0300 Subject: [PATCH] [#846] morph/notary: Add nonce parameter to notary invocation method This prevents notary requests collisions for TXs that contains equals hashable fields. Signed-off-by: Pavel Karpy --- pkg/innerring/state.go | 3 ++- pkg/morph/client/notary.go | 22 ++++++++++++++-------- pkg/morph/client/static.go | 3 ++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 36ce2923..b0e014a3 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -94,7 +94,8 @@ func (s *Server) voteForSidechainValidator(validators keys.PublicKeys) error { epoch := s.EpochCounter() s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { - err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), voteMethod, int64(epoch), validators) + // FIXME: do not use constant nonce for alphabet NR: #844 + err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), 1, voteMethod, int64(epoch), validators) if err != nil { s.log.Warn("can't invoke vote method in alphabet contract", zap.Int8("alphabet_index", int8(letter)), diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 594a30f8..21dfb8fd 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -16,6 +16,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/nspcc-dev/neofs-node/pkg/util/rand" "go.uber.org/zap" ) @@ -248,6 +249,7 @@ func (c *Client) UpdateNotaryList(list keys.PublicKeys) error { return c.notaryInvokeAsCommittee( setDesignateMethod, + 1, // FIXME: do not use constant nonce for alphabet NR: #844 noderoles.P2PNotary, list, ) @@ -271,6 +273,7 @@ func (c *Client) UpdateNeoFSAlphabetList(list keys.PublicKeys) error { return c.notaryInvokeAsCommittee( setDesignateMethod, + 1, // FIXME: do not use constant nonce for alphabet NR: #844 noderoles.NeoFSAlphabet, list, ) @@ -281,10 +284,10 @@ func (c *Client) UpdateNeoFSAlphabetList(list keys.PublicKeys) error { // it fallbacks to a simple `Invoke()`. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...interface{}) error { +func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, method string, args ...interface{}) error { if c.multiClient != nil { return c.multiClient.iterateClients(func(c *Client) error { - return c.NotaryInvoke(contract, fee, method, args...) + return c.NotaryInvoke(contract, fee, nonce, method, args...) }) } @@ -292,9 +295,12 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, method s return c.Invoke(contract, fee, method, args...) } - return c.notaryInvoke(false, true, contract, method, args...) + return c.notaryInvoke(false, true, contract, nonce, method, args...) } +// randSource is a source of random numbers. +var randSource = rand.New() + // NotaryInvokeNotAlpha does the same as NotaryInvoke but does not use client's // private key in Invocation script. It means that main TX of notary request is // not expected to be signed by the current node. @@ -311,7 +317,7 @@ func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, return c.Invoke(contract, fee, method, args...) } - return c.notaryInvoke(false, false, contract, method, args...) + return c.notaryInvoke(false, false, contract, randSource.Uint32(), method, args...) } // NotarySignAndInvokeTX signs and sends notary request that was received from @@ -359,16 +365,16 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { return nil } -func (c *Client) notaryInvokeAsCommittee(method string, args ...interface{}) error { +func (c *Client) notaryInvokeAsCommittee(method string, nonce uint32, args ...interface{}) error { designate, err := c.GetDesignateHash() if err != nil { return err } - return c.notaryInvoke(true, true, designate, method, args...) + return c.notaryInvoke(true, true, designate, nonce, method, args...) } -func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, method string, args ...interface{}) error { +func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, method string, args ...interface{}) error { alphabetList, err := c.notary.alphabetSource() // prepare arguments for test invocation if err != nil { return err @@ -417,7 +423,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint // prepare main tx mainTx := &transaction.Transaction{ - Nonce: 1, + Nonce: nonce, SystemFee: test.GasConsumed, ValidUntilBlock: until, Script: test.Script, diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 11387042..fe39fb68 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -78,7 +78,8 @@ func (s StaticClient) Morph() *Client { func (s StaticClient) Invoke(method string, args ...interface{}) error { if s.tryNotary { if s.alpha { - return s.client.NotaryInvoke(s.scScriptHash, s.fee, method, args...) + // FIXME: do not use constant nonce for alphabet NR: #844 + return s.client.NotaryInvoke(s.scScriptHash, s.fee, 1, method, args...) } return s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, method, args...)