diff --git a/neps/nep-0461.md b/neps/nep-0461.md new file mode 100644 index 000000000..1d6034ea7 --- /dev/null +++ b/neps/nep-0461.md @@ -0,0 +1,79 @@ +--- +NEP: 0461 +Title: Prefix Tag for Signed Messages +Author: Evgeny Kapun , Gallardo Guillermo , Firat Sertgoz +DiscussionsTo: https://github.com/nearprotocol/neps/pull/461 +Status: Review +Type: Protocol +Category: Runtime +Version: 1.0.0 +Created: 14-Feb-2023 +Updated: 14-Feb-2023 +--- + +## Summary +A proposal to include a standardized prefix in all standardized signable messages, to distinguish between (1) actionable messages (i.e. those that are validated on chain), (2) non-actionable messages (i.e. those that are used off-chain), and (3) [classic transactions](https://nomicon.io/RuntimeSpec/Transactions). + +Particularly, we propose to prepend an implicit prefix to the structure being signed using the following rules: + +| Implicit Prefix | Message | +| - | - | +| $< 2^{30}$ | [Classic Transactions](https://nomicon.io/RuntimeSpec/Transactions) | +| $2^{30}$ + NEP-number | On-chain Actionable Message, e.g. [`SignedDelegateAction`](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | +| $2^{31}$ + NEP-number | Off-chain Message, e.g. [`signMessage`](https://github.com/near/NEPs/pull/413) | + +## Motivation +As the ecosystem grows, more standards will appear, enabling users to sign messages that are not transactions (e.g. [NEP413](https://github.com/near/NEPs/pull/413/), and [NEP366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md)). If such messages collide with transactions, a malicious app could ask users to sign them, only to later relay them as valid transactions to the network. + +## Rationale and alternatives + +In NEAR, users sign transactions that are later relayed to the network. At the moment of being relayed, the transactions are simple streams of bytes that a node then parses into a [valid transaction](https://nomicon.io/RuntimeSpec/Transactions). + +As the protocol expands, more messages will be added for users to sign. We want users to be able to use the protocol safely, making sure that all those signed messages cannot be interpreted as a valid transaction. + +In practice, what users sign is the `sha256` hash of a [borsh-serialized](https://borsh.io) structure. This is: + +```ts +sha256.hash(Borsh.serialize(MessageStructure)) +``` + +Including a large `u32` prefix allows to easily distinguish transactions from messages, ensuring that they never overlap. + +```ts +sha256.hash(Borsh.serialize(large-number) + Borsh.serialize(MessageStructure)) +``` + +This is because the first field of a [valid transaction](https://nomicon.io/RuntimeSpec/Transactions) is an `AccountId`, which is encoded as `string length ` + `string chars `. Adding a prefix in the range of $(2^{30}, 2^{32})$ will automatically make the message deserialize into an invalid transaction, since no `AccountId` has more than 64 chars. + + +## Specification + +### On-Chain Messages +All actionable messages, i.e. those that ARE validated on-chain, should prepend an implicit `prefix: u32` with fixed value $2^{30}$ + NEP-number. + +For example, if we implement a new actionable message `ActionableMessage` destined to be used on-chain, and the proposal has the number `NEP400`, then the message must have the following form: + +```ts +// 2**30 + 400 = 1073742224 +sha256.hash(Borsh.serialize(1073742224) + Borsh.serialize(ActionableMessage)) +``` + +### Off-Chain Messages +All non-actionable messages, i.e. those that are NOT validated on-chain, should prepend an implicit `prefix: u32` with fixed value $2^{31}$ + NEP-number. + +For example, if we implement a new non-actionable message `NonActionableMessage`, destined to be used off-chain, and the proposal has the number `NEP400`, then the message to be signed is: + +```ts +// 2**31 + 400 = 2147484048 +sha256.hash(Borsh.serialize(2147484048) + Borsh.serialize(NonActionableMessage)) +``` + +## Security Implications + +By implementing this NEP, we can be sure that all new messages do not collide with classic transactions. + +## Drawbacks + +We will need to update [NEP366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) to follow this standard, and make sure all future NEPs follow it, which might be hard to track. + +If at any point there is an update on how transactions are encoded, this NEP could stop being valid.