github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/docs/notary.md (about)

     1  # NeoGo P2P signature collection (notary) service
     2  
     3  P2P signature (notary) service is a NeoGo node extension that allows several
     4  parties to sign one transaction independently of chain and without going beyond the
     5  chain environment. The on-chain P2P service is aimed to automate, accelerate and
     6  secure the process of signature collection. The service was initially designed as
     7  a solution for
     8  [multisignature transaction forming](https://github.com/neo-project/neo/issues/1573#issue-600384746)
     9  and described in the [proposal](https://github.com/neo-project/neo/issues/1573#issuecomment-704874472).
    10  
    11  The original problem definition:
    12  > Several parties want to sign one transaction, it can either be a set of signatures
    13  > for multisignature signer or multiple signers in one transaction. It's assumed
    14  > that all parties can generate the same transaction (with the same hash) without
    15  > any interaction, which is the case for oracle nodes or NeoFS inner ring nodes.
    16  > 
    17  > As some of the services using this mechanism can be quite sensitive to the
    18  > latency of their requests processing, it should be possible to construct a complete
    19  > transaction within the time frame between two consecutive blocks.
    20  
    21  
    22  ## Components and functionality
    23  The service consists of a native contract and a node module. Native contract is
    24  mostly concerned with verification, fees and payment guarantees, while module is
    25  doing the actual work. It uses generic `Conflicts` and `NotValidBefore`
    26  transaction attributes for its purposes as well as an additional special one
    27  (`Notary assisted`).
    28  
    29  A new designated role is added, `P2PNotary`. It can have an arbitrary number of
    30  keys associated with it.
    31  
    32  To use the service, one should pay some GAS, so below we operate with `FEE` as a unit of cost
    33  for this service. `FEE` is set to be 0.1 GAS.
    34  
    35  We'll also use `NKeys` definition as the number of keys that participate in the
    36  process of signature collection. This is the number of keys that could potentially
    37  sign the transaction, for transactions lacking appropriate witnesses that would be
    38  the number of witnesses, for "M out of N" multisignature scripts that's N, for
    39  combination of K standard signature witnesses and L multisignature "M out of N"
    40  witnesses that's K+N*L.
    41  
    42  ### Transaction attributes
    43  
    44  #### Conflicts
    45  
    46  This attribute makes the chain accept one transaction of the two conflicting only
    47  and adds an ability to give a priority to any of the two if needed. This
    48  attribute was originally proposed in
    49  [neo-project/neo#1991](https://github.com/neo-project/neo/issues/1991).
    50  
    51  The attribute has Uint256 data inside containing the hash of conflicting
    52  transaction. It is allowed to have multiple attributes of this type.
    53  
    54  #### NotValidBefore
    55  
    56  This attribute makes transaction invalid before certain height. This attribute
    57  was originally proposed in
    58  [neo-project/neo#1992](https://github.com/neo-project/neo/issues/1992).
    59  
    60  The attribute has uint32 data inside which is the block height starting from
    61  which the transaction is considered to be valid. It can be seen as the opposite
    62  of `ValidUntilBlock`. Using both allows to have a window of valid block numbers
    63  that this transaction could be accepted into. Transactions with this attribute
    64  are not accepted into mempool before specified block is persisted.
    65  
    66  It can be used to create some transactions in advance with a guarantee that they
    67  won't be accepted until the specified block.
    68  
    69  #### NotaryAssisted
    70  
    71  This attribute holds one byte containing the number of transactions collected
    72  by the service. It could be 0 for fallback transaction or `NKeys` for a normal
    73  transaction that completed its P2P signature collection. Transactions using this
    74  attribute need to pay additional network fee of (`NKeys`+1)×`FEE`. This attribute
    75  could be only be used by transactions signed by the notary native contract.
    76  
    77  ### Native Notary contract
    78  
    79  It exposes several methods to the outside world:
    80  
    81  | Method | Parameters | Return value | Description |
    82  | --- | --- | --- | --- |
    83  | `onNEP17Payment` | `from` (uint160) - GAS sender account.<br>`amount` (int) - amount of GAS to deposit.<br>`data` represents array of two parameters: <br>1. `to` (uint160) - account of the deposit owner.<br>2. `till` (int) - deposit lock height. | `bool` | Automatically called after GAS transfer to Notary native contract address and records deposited amount as belonging to `to` address with a lock till `till` chain's height. Can only be invoked from native GAS contract. Must be witnessed by `from`. `to` can be left unspecified (null), with a meaning that `to` is the same address as `from`. `amount` can't be less than 2×`FEE` for the first deposit call for the `to` address. Each successive deposit call must have `till` value equal to or more than the previous successful call (allowing for renewal), if it has additional amount of GAS it adds up to the already deposited value.|
    84  | `lockDepositUntil` | `address` (uint160) - account of the deposit owner.<br>`till` (int) - new height deposit is valid until (can't be less than previous value and can't be less than the height when transaction is accepted to the chain plus one). | `void` | Updates deposit expiration value. Must be witnessed by `address`. |
    85  | `withdraw` | `from` (uint160) - account of the deposit owner.<br>`to` (uint160) - account to transfer GAS to. | `bool` | Sends all deposited GAS for `from` address to `to` address. Must be witnessed by `from`. `to` can be left unspecified (null), with a meaning that `to` is the same address as `from`. It can only be successful if the lock has already expired, attempting to withdraw the deposit before that height fails. Partial withdrawal is not supported. Returns boolean result, `true` for successful calls and `false` for failed ones. |
    86  | `balanceOf` | `addr` (uint160) - account of the deposit owner. | `int` | Returns deposited GAS amount for specified address (integer). |
    87  | `expirationOf` | `addr` (uint160) - account of the deposit owner. | `int` | Returns deposit lock height for specified address (integer). |
    88  | `verify` | `signature` (signature) - notary node signature bytes for verification. | `bool` | This is used to verify transactions with notary contract specified as a signer, it needs one signature in the invocation script and it checks for this signature to be made by one of designated keys, effectively implementing "1 out of N" multisignature contract. |
    89  | `getMaxNotValidBeforeDelta` | | `int` | Returns `MaxNotValidBeforeDelta` constraint. Default value is 140. |
    90  | `setMaxNotValidBeforeDelta` | `value` (int) | `void` | Set `MaxNotValidBeforeDelta` constraint. Must be witnessed by committee. |
    91  
    92  See the [Notary deposit guide](#1.-Notary-deposit) section on how to deposit
    93  funds to Notary native contract and manage the deposit.
    94  
    95  ### P2PNotaryRequest payload
    96  
    97  A new broadcasted payload type is introduced for notary requests. It's
    98  distributed via regular inv-getdata mechanism like transactions, blocks or
    99  consensus payloads. An ordinary P2P node verifies it, saves in a structure
   100  similar to mempool and relays. This payload has witness (standard
   101  single-signature contract) attached signing all of the payload.
   102  
   103  This payload has two incomplete transactions inside:
   104  
   105  - *Fallback tx*. This transaction has P2P Notary contract as a sender and service
   106    request sender as an additional signer. It can't have a witness for Notary
   107    contract, but it must have proper witness for request sender. It must have
   108    `NotValidBefore` attribute that is no more than `MaxNotValidBeforeDelta` higher
   109    than the current chain height and it must have `Conflicts` attribute with the
   110    hash of the main transaction. It at the same time must have `Notary assisted`
   111    attribute with a count of zero.
   112  - *Main tx*. This is the one that actually needs to be completed; it:
   113    1. *either* doesn't have all witnesses attached
   114    2. *or* has a partial multisignature only
   115    3. *or* have not all witnesses attached and some of the rest are partial multisignature
   116    
   117    This transaction must have `Notary assisted` attribute with a count of `NKeys`
   118    (and Notary contract as one of the signers).
   119  
   120  See the [Notary request submission guide](#2-request-submission) to learn how to
   121  construct and send the payload.
   122  
   123  ### Notary node module
   124  
   125  Node module with the designated key monitors the network for `P2PNotaryRequest`
   126  payloads. It maintains a list of current requests grouped by main transaction
   127  hash. When it receives enough requests to correctly construct all transaction
   128  witnesses, it does so, adds a witness of its own (for Notary contract witness) and
   129  sends the resulting transaction to the network.
   130  
   131  If the main transaction with all witnesses attached still can't be validated
   132  due to any fee (or other) issues, the node waits for `NotValidBefore` block of
   133  the fallback transaction to be persisted.
   134  
   135  If `NotValidBefore` block is persisted and there are still some signatures
   136  missing (or the resulting transaction is invalid), the module sends all the
   137  associated fallback transactions for the main transaction.
   138  
   139  After processing, service request is deleted from the module.
   140  
   141  See the [NeoGo P2P signature extensions](#NeoGo P2P signature extensions) on how
   142  to enable notary-related extensions on chain and
   143  [NeoGo Notary service node module](#NeoGo Notary service node module) on how to
   144  set up Notary service node.
   145  
   146  ## Environment setup
   147  
   148  To run P2P signature collection service on your network, you need to do:
   149  * Set up [`P2PSigExtensions`](#NeoGo P2P signature extensions) for all nodes in
   150    the network.
   151  * Set notary node keys in `RoleManagement` native contract.
   152  * [Configure](#NeoGo Notary service node module) and run appropriate number of
   153    notary nodes with keys specified in `RoleManagement` native contract (at least
   154    one node is necessary to complete signature collection).
   155  
   156  After service is running, you can [create and send](#Notary request lifecycle guide)
   157  notary requests to the network.
   158  
   159  ### NeoGo P2P signature extensions
   160  
   161  As far as Notary service is an extension of the standard NeoGo node, it should be
   162  enabled and properly configured before usage.
   163  
   164  #### Configuration
   165  
   166  To enable P2P signature extensions add `P2PSigExtensions` subsection set to
   167  `true` to `ProtocolConfiguration` section of your node config. This enables all
   168  notary-related logic in the network, i.e. allows your node to accept and validate
   169  `NotValidBefore`, `Conflicts` and `NotaryAssisted` transaction attribute, handle,
   170  verify and broadcast `P2PNotaryRequest` P2P payloads, properly initialize native
   171  Notary contract and designate `P2PNotary` node role in RoleManagement native
   172  contract.
   173  
   174  Currently, Notary contract activation height is not configurable and is always
   175  set to 0 (if `P2PSigExtensions` are enabled).
   176  
   177  Note, that even if `P2PSigExtensions` config subsection enables notary-related
   178  logic in the network, it still does not turn your node into notary service node.
   179  To enable notary service node functionality refer to the
   180  [NeoGo Notary service](#NeoGo-Notary-service-node-module) documentation.
   181  
   182  ##### Example
   183  
   184  ```
   185    P2PSigExtensions: true
   186  ```
   187  
   188  
   189  ### NeoGo Notary service node module
   190  
   191  NeoGo node can act as notary service node (the node that accumulates notary
   192  requests, collects signatures and releases fully-signed transactions). It must
   193  have a wallet with a key belonging to one of network's designated notary nodes
   194  (stored in `RoleManagement` native contract). Also, the node must be connected to
   195  a network with enabled P2P signature extensions, otherwise problems with states
   196  and peer disconnections will occur.
   197  
   198  Notary service node doesn't need [RPC service](rpc.md) to be enabled because it
   199  receives notary requests and broadcasts completed transactions via P2P protocol.
   200  However, enabling [RPC service](rpc.md) allows to send notary requests directly
   201  to the notary service node and avoid P2P communication delays.
   202  
   203  #### Configuration
   204  
   205  To enable notary service node check firstly that
   206  [P2PSignatureExtensions](#NeoGo P2P signature extensions) are properly set up.
   207  Then add `P2PNotary` subsection to `ApplicationConfiguration` section of your
   208  node config.
   209  
   210  Parameters:
   211  * `Enabled`: boolean value, enables/disables the service node, `true` for service
   212    node to be enabled
   213  * `UnlockWallet`: notary node wallet configuration:
   214      - `Path`: path to NEP-6 wallet.
   215      - `Password`: password for the account to be used by notary node.
   216  
   217  ##### Example
   218  
   219  ```
   220  P2PNotary:
   221    Enabled: true
   222    UnlockWallet:
   223      Path: "/notary_node_wallet.json"
   224      Password: "pass"
   225  ```
   226  
   227  
   228  ## Notary request lifecycle guide
   229  
   230  Below are presented all stages each P2P signature collection request goes through. Use
   231  stages 1 and 2 to create, sign and submit P2P notary request. Stage 3 is
   232  performed by the notary service; it does not require user's intervention and is given
   233  for informational purposes. Stage 4 contains advice to check for notary request
   234  results.
   235  
   236  ### 1. Notary deposit
   237  
   238  To guarantee that payment to the notary node will still be done if things go wrong,
   239  sender's deposit to the Notary native contract is used. Before the notary request will be
   240  submitted, you need to deposit enough GAS to the contract, otherwise, request
   241  won't pass verification.
   242  
   243  Notary native contract supports `onNEP17Payment` method. Thus, to deposit funds to
   244  the Notary native contract, transfer the desired amount of GAS to the contract
   245  address. Use
   246  [func (*Client) TransferNEP17](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.97.2/pkg/rpcclient#Client.TransferNEP17)
   247  with the `data` parameter matching the following requirements:
   248  - `data` should be an array of two elements: `to` and `till`.
   249  - `to` denotes the receiver of the deposit. It can be nil in case `to` equals
   250    the GAS sender.
   251  - `till` denotes chain's height before which deposit is locked and can't be
   252    withdrawn. `till` can't be less than the current chain height. `till`
   253    can't be less than the current `till` value for the deposit if the deposit
   254    already exists. `till` can be set to the provided value iff the transaction
   255    sender is the owner of the deposit, otherwise the provided `till` value will
   256    be overridden by the system. If the sender is not the deposit owner, the
   257    overridden `till` value is either set to be the current chain height + 5760
   258    (for the newly added deposit) or set to the old `till` value (for the existing
   259    deposit).
   260  
   261  Note, that the first deposit call for the `to` address can't transfer less than 2×`FEE` GAS.
   262  Deposit is allowed for renewal, i.e. consequent `deposit` calls for the same `to`
   263  address add up a specified amount to the already deposited value.
   264  
   265  After GAS transfer is successfully submitted to the chain, use [Notary native
   266  contract API](#Native Notary contract) to manage your deposit.
   267  
   268  Note, that regular operation flow requires the deposited amount of GAS to be
   269  sufficient to pay for *all* fallback transactions that are currently submitted (all
   270  in-flight notary requests). The default deposit sum for one fallback transaction
   271  should be enough to pay the fallback transaction fees which are system fee and
   272  network fee. Fallback network fee includes (`NKeys`+1)×`FEE` = (0+1)×`FEE` = `FEE`
   273  GAS for `NotaryAssisted` attribute usage and regular fee for the fallback size.
   274  If you need to submit several notary requests, ensure that the deposited amount is
   275  enough to pay for all fallbacks. If the deposited amount is not enough to pay the
   276  fallback fees, `Insufficiend funds` error will be returned from the RPC node
   277  after notary request submission.
   278  
   279  ### 2. Request submission
   280  
   281  Once several parties want to sign one transaction, each of them should generate
   282  the transaction, wrap it into `P2PNotaryRequest` payload and send it to the known RPC
   283  server via [`submitnotaryrequest` RPC call](./rpc.md#submitnotaryrequest-call).
   284  Note, that all parties must generate the same main transaction while fallbacks
   285  can differ.
   286  
   287  To create a notary request, you can use [NeoGo RPC client](./rpc.md#Client). The
   288  procedure below uses only basic RPC client functions and show all of the notary
   289  request internals. You can use much simpler Actor interface in the notary
   290  subpackage with an example written in Go doc.
   291  
   292  1. Prepare a list of signers with scopes for the main transaction (i.e. the
   293     transaction that signatures are being collected for, that will be `Signers`
   294     transaction field). Use the following rules to construct the list:
   295     * First signer is the one who pays the transaction fees.
   296     * Each signer is either a multisignature or a standard signature or a contract
   297       signer.
   298     * Multisignature and signature signers can be combined.
   299     * Contract signer can be combined with any other signer.
   300  
   301     Include Notary native contract in the list of signers with the following
   302     constraints:
   303     * Notary signer hash is the hash of a native Notary contract that can be fetched
   304       from the notary RPC client subpackage (notary.Hash)
   305     * A notary signer must have `None` scope.
   306     * A notary signer shouldn't be placed at the beginning of the signer list
   307       because Notary contract does not pay main transaction fees. Other positions
   308       in the signer list are available for a Notary signer.
   309  2. Construct a script for the main transaction (that will be `Script` transaction
   310     field) and calculate system fee using regular rules (that will be `SystemFee`
   311     transaction field). Probably, you'll perform one of these actions:
   312     1. If the script is a contract method call, use `invokefunction` RPC API
   313        [func (*Client) InvokeFunction](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.97.2/pkg/rpcclient#Client.InvokeFunction)
   314        and fetch the script and the gas consumed from the result.
   315     2. If the script is more complicated than just a contract method call,
   316        construct the script manually and use `invokescript` RPC API
   317        [func (*Client) InvokeScript](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.97.2/pkg/rpcclient#Client.InvokeScript)
   318        to fetch the gas consumed from the result.
   319     3. Or just construct the script and set system fee manually.
   320  3. Calculate the height main transaction is valid until (that will be
   321     `ValidUntilBlock` transaction field). Consider the following rules for `VUB`
   322     value estimation:
   323        * `VUB` value must not be lower than the current chain height.
   324        * The whole notary request (including fallback transaction) is valid until
   325          the same `VUB` height.
   326        * `VUB` value must be lower than notary deposit expiration height. This
   327          condition guarantees that the deposit won't be withdrawn before notary
   328          service payment.
   329        * All parties must provide the same `VUB` for the main transaction. 
   330  4. Construct the list of main transaction attributes (that will be `Attributes`
   331     transaction field). The list must include `NotaryAssisted` attribute with
   332     `NKeys` equals the overall number of the keys to be collected excluding notary and
   333     other contract-based witnesses. For m out of n multisignature request
   334     `NKeys = n`. For multiple standard signature request, signers `NKeys` equals
   335     the standard signature signers count.
   336  5. Construct a list of accounts (`wallet.Account` structure from the `wallet`
   337     package) to calculate network fee for the transaction
   338     using the following rules. This list will be used in the next step.
   339     - The number and the order of the accounts should match the transaction signers
   340       constructed at step 1.
   341     - An account for a contract signer should have `Contract` field with `Deployed` set
   342       to `true` if the corresponding contract is deployed on chain.
   343     - An account for a signature or a multisignature signer should have `Contract` field
   344       with `Deployed` set to `false` and `Script` set to the signer's verification
   345       script.
   346     - An account for a notary signer is **just a placeholder** and should have
   347       `Contract` field with `Deployed` set to `true`. Its `Invocation` witness script
   348       parameters will be guessed by the `verify` method signature of Notary contract
   349       during the network fee calculation at the next step.
   350       
   351  6. Fill in the main transaction `Nonce` field.
   352  7. Construct a list of main transactions witnesses (that will be `Scripts`
   353     transaction field). Uses standard rules for witnesses of not yet signed
   354     transaction (it can't be signed at this stage because network fee is missing):
   355     - A contract-based witness should have `Invocation` script that pushes arguments
   356       on stack (it may be empty) and empty `Verification` script. If multiple notary
   357       requests provide different `Invocation` scripts, the first one will be used
   358       to construct contract-based witness. If non-empty `Invocation` script is
   359       specified then it will be taken into account during network fee calculation.
   360       In case of an empty `Invocation` script, its parameters will be guessed from
   361       the contract's `verify` signature during network fee calculation.
   362     - A **Notary contract witness** (which is also a contract-based witness) should
   363       have empty `Verification` script. `Invocation` script should be either empty
   364       (allowed for main transaction and forbidden for fallback transaction) or of
   365       the form [opcode.PUSHDATA1, 64, make([]byte, 64)...] (allowed for main
   366       transaction and required for fallback transaction by the Notary subsystem to
   367       pass verification), i.e. to be a placeholder for a notary contract signature.
   368       Both ways are OK for network fee calculation.
   369     - A standard signature witness must have regular `Verification` script filled
   370       even if the `Invocation` script is to be collected from other notary
   371       requests.
   372       `Invocation` script **should be empty**.
   373     - A multisignature witness must have regular `Verification` script filled even
   374       if `Invocation` script is to be collected from other notary requests.
   375       `Invocation` script **should be empty**.
   376  8. Calculate network fee for the transaction (that will be `NetworkFee`
   377     transaction field). Use [func (*Client) CalculateNetworkFee](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.99.2/pkg/rpcclient#Client.CalculateNetworkFee)
   378     method with the main transaction given to it.
   379  9. Fill in all signatures that can be provded by the client creating request,
   380     that includes simple-signature accounts and multisignature accounts where
   381     the client has one of the keys (in which case an invocation script is
   382     created that pushes just one signature onto the stack).
   383  10. Sign and submit P2P notary request. Use
   384      [func (*Actor) Notarize](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/rpcclient/notary#Actor.Notarize) for it.
   385      - Use the signed main transaction from step 9 as `mainTx` argument.
   386      
   387      `Notarize` will construct and sign a fallback transaction using `Actor`
   388      configuration (just a simple `RET` script by default), pack both transactions
   389      into a P2PNotaryRequest and submit it to the RPC node. It returns hashes of
   390      the main and fallback transactions as well as their `ValidUntilBlock` value.
   391      If you need more control over fallback transaction use `Actor` options or
   392      [func (*Actor) SendRequest](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/rpcclient/notary#Actor.SendRequest)
   393      API.
   394  
   395  After P2PNotaryRequests are sent, participants should wait for one of their
   396  transactions (main or fallback) to get accepted into one of subsequent blocks.
   397  
   398  ### 3. Signatures collection and transaction release
   399  
   400  A valid P2PNotaryRequest payload is distributed via P2P network using standard
   401  broadcasting mechanisms until it reaches the designated notary nodes that have the
   402  respective node module active. They collect all payloads for the same main
   403  transaction until enough signatures are collected to create proper witnesses for
   404  it. Then, they attach all witnesses required and send this transaction as usual
   405  and monitor subsequent blocks for its inclusion.
   406  
   407  All the operations leading to successful transaction creation are independent
   408  of the chain and could easily be done within one block interval. So, if the
   409  first service request is sent at the current height `H`, the main transaction
   410  is highly likely to be a part of `H+1` block.
   411   
   412  ### 4. Results monitoring
   413  
   414  Once the P2PNotaryRequest reaches RPC node, it is added to the notary request pool.
   415  Completed or outdated requests are removed from the pool. Use
   416  [NeoGo notification subsystem](./notifications.md) to track request addition and
   417  removal:
   418  
   419  - Use RPC `subscribe` method with `notary_request_event` stream name parameter to
   420    subscribe to `P2PNotaryRequest` payloads that are added or removed from the
   421    notary request pool.
   422  - Use `sender` or `signer` filters to filter out a notary request with the desired
   423    request senders or main tx signers.
   424  
   425  Use the notification subsystem to track that the main or the fallback transaction
   426  is accepted to the chain:
   427  
   428  - Use RPC `subscribe` method with `transaction_added` stream name parameter to
   429    subscribe to transactions that are accepted to the chain.
   430  - Use `sender` filter with the Notary native contract hash to filter out fallback
   431    transactions sent by the Notary node. Use `signer` filter with the notary request
   432    sender address to filter out the fallback transactions sent by the specified
   433    sender.
   434  - Use `sender` or `signer` filters to filter out the main transaction with the desired
   435    sender or signers. You can also filter out the main transaction using Notary
   436    contract `signer` filter.
   437  - Don't rely on `sender` and `signer` filters only, also check that the received
   438    transaction has `NotaryAssisted` attribute with the expected `NKeys` value.
   439  
   440  Use the notification subsystem to track main or fallback transaction execution
   441  results.
   442  
   443  Moreover, you can use all regular RPC calls to track main or fallback transaction
   444  invocation: `getrawtransaction`, `getapplicationlog` etc.
   445  
   446  ## Notary service use-cases
   447  
   448  Several use-cases where Notary subsystem can be applied are described below.
   449  
   450  ### Committee-signed transactions
   451  
   452  The signature collection problem occurs every time committee participants need
   453  to submit a transaction with `m out of n` multisignature, i.g.:
   454  - transfer initial supply of NEO and GAS from a committee multisignature account to
   455    other addresses on new chain start
   456  - tune valuable chain parameters like gas per block, candidate register price,
   457    minimum contract deployment fee, Oracle request price, native Policy values etc
   458  - invoke non-native contract methods that require committee multisignature witness
   459  
   460  Current solution offers off-chain non-P2P signature collection (either manual
   461  or using some additional network connectivity). It has an obvious downside of
   462  reliance on something external to the network. If it's manual, it's slow and
   463  error-prone; if it's automated, it requires additional protocol for all the
   464  parties involved. For the protocol used by oracle nodes, it also means
   465  nodes explicitly exposing to each other.
   466  
   467  With the Notary service all signature collection logic is unified and is on chain already.
   468  The only thing that committee participants should perform is to create and submit
   469  a P2P notary request (can be done independently). Once the sufficient number of signatures
   470  is collected by the service, the desired transaction will be applied and pass committee
   471  witness verification.
   472  
   473  ### NeoFS Inner Ring nodes
   474  
   475  Alphabet nodes of the Inner Ring signature collection is a particular case of committee-signed
   476  transactions. Alphabet nodes multisignature is used for various cases, such as:
   477  - main chain and side chain funds synchronization and withdrawal
   478  - bootstrapping new storage nodes to the network
   479  - network map management and epoch update
   480  - containers and extended ACL management
   481  - side chain governance update
   482  
   483  Non-notary on-chain solution for Alphabet nodes multisignature forming is
   484  imitated via contracts collecting invocations of their methods signed by standard
   485  signature of each Alphabet node. Once the sufficient number of invocations is
   486  collected, the invocation is performed.
   487  
   488  The described solution has several drawbacks:
   489  
   490  - it can only be app-specific (meaning that for every use case this logic would
   491    be duplicated) because we can't create transactions from transactions (thus
   492    using proper multisignature account is not possible)
   493  - for `m out of n` multisignature we need at least `m` transactions instead of
   494    one we really wanted to have; but actually we'll create and process `n` of
   495    them, so this adds substantial overhead to the chain
   496  - some GAS is inevitably wasted because any invocation could either go the easy
   497    path (just adding a signature to the list) or really invoke the function we
   498    wanted to (when all signatures are in place), so test invocations don't really
   499    help and the user needs to add some GAS to all of these transactions
   500  
   501  Notary on-chain Alphabet multisignature collection solution
   502  [uses Notary subsystem](https://github.com/nspcc-dev/neofs-node/pull/404) to
   503  successfully solve these problems, e.g. to calculate precisely the amount of GAS to
   504  pay for contract invocation witnessed by Alphabet nodes (see
   505  [nspcc-dev/neofs-node#47](https://github.com/nspcc-dev/neofs-node/issues/47)),
   506  to reduce container creation delay
   507  (see [nspcc-dev/neofs-node#519](https://github.com/nspcc-dev/neofs-node/issues/519))
   508  etc.
   509  
   510  ### Contract-sponsored (free) transactions
   511  
   512  The original problem and solution are described in
   513  [neo-project/neo#2577](https://github.com/neo-project/neo/issues/2577) discussion.