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.