Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Proposal: add meta transaction proposal #165

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Jim8y
Copy link
Contributor

@Jim8y Jim8y commented Oct 17, 2023

Based on EIP-712, propose neo's standard meta transaction format.

Major difference:

chainId = > networkId,
data = > script.

'''Data Structures''':

  • '''Domain''':
    ** networkId: Integer representing the NEO network identifier.
    ** version: String representing the version of the meta-transaction format.
  • '''Message''':
    ** nonce: Integer, a unique number ensuring each signature is unique.
    ** from: String, address of the sender.
    ** to: String, address of the receiver.
    ** value: Integer, amount being transferred in smallest unit.
    ** script: Bytes, script related to the transaction.

@roman-khimov
Copy link
Contributor

Refs. #68. But I don't think it'll work the way it's laid out currently, too many E-chain concepts, too few N3 ones.

@Jim8y
Copy link
Contributor Author

Jim8y commented Oct 17, 2023

Refs. #68. But I don't think it'll work the way it's laid out currently, too many E-chain concepts, too few N3 ones.

Will update under discussion, we will need to make this standard to provide a few services.

@Jim8y
Copy link
Contributor Author

Jim8y commented Oct 17, 2023

@dusmart can you please help me update this?

@dusmart
Copy link

dusmart commented Oct 18, 2023

@dusmart can you please help me update this?

Actually, there is two big differences between E-letter chain and N3 as far as I'm concerned under the discussion of if ERC-2771 can work on N3.

  1. address, with the same private key, you will get different addresses on them
  2. external function call between contracts, you can easily append an argument on E-letter chain during calling external contracts, while you can not do that on N3. N3 caller can only pass the number of arguments required by callee.

The first one matters because there is an address of the sender in this Data Structure.
The second one matters because there is a script in this Data Structure. You can not easily append a real sender as an extra argument during executing external call in the script. Therefore, the callee can not know who is really calling it.

@Hecate2
Copy link

Hecate2 commented Oct 18, 2023

  NEP: 23
  Title: NEO Meta-Transaction Proposal
  Author: Jinghui Liao (jimmy@r3e.network)
  Type: Standard
  Status: Draft
  Created: 2023-10-17
  Requires (*optional): NEP-2
  Replaces (*optional): 

==Abstract==

This proposal introduces a standardized format for meta-transactions on the NEO platform, aiming to enhance user experience by making transactions more understandable and transparent. It allows users to sign human-readable, structured data, ensuring both usability and security.

==Motivation==

With the increasing complexity of blockchain applications and the evolution of smart contract interactions, there's a clear need for a more user-friendly approach to transaction signing on NEO. The current protocol doesn't provide a standardized way to sign structured, human-readable data, which may lead to confusion and potential misuse. This proposal fills this gap by defining a clear and standardized format for meta-transactions.

==Specification==

A meta-transaction consists of structured data with fields like domain, message, nonce, sender, receiver, value, and related data. For signing, this structured data is transformed into a byte representation, which is then signed using the signer's NEO private key. Signature verification is analogous to NEO's current transaction verification methodology.

=== Definitions ===

  • '''Meta-Transaction''': A transaction that contains structured data and a signature.
  • '''Domain''': A collection of data that represents the context of the meta-transaction, including networkId and version.
  • '''Signer''': An entity that produces a signature for a meta-transaction.

=== Byte Representation ===
For signing purposes, the structured data needs to be transformed into a byte representation. This can be achieved by serializing each field into its byte representation and concatenating them.

  1. '''Data Structures''':

    • '''Domain''':
      ** name: String representing the domain name
      ** networkId: Integer representing the NEO network identifier.
      ** version: String representing the version of the meta-transaction format.
      ** verifyingContract: Address of the contract that will verify the user's signature and relay the transaction
    • '''ForwardRequest''':
      ** nonce: Integer, a unique number ensuring each signature is unique.
      ** from: String, address of the sender.
      ** to: String, address of the receiver.
      ** value: Integer, amount being transferred in smallest unit.
      ** gas: Interger, minimum amount of gas the proxy contract should provide
      ** data: Bytes, callee contract address and method as well as the arguments related to the meta transaction.
  2. '''Serialization Process''':

    • use keccak256 as the hash algorithm
    • use abi.encode or abi.encodePacked as the serialization method
    • Data is serialized in the order of Domain followed by ForwardRequest.
      • the final message is keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash))
      • domainSeparator is keccak256(abi.encode(typeHash, nameHash, versionHash, networkId, contractAddress))
        • typeHash is keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
        • nameHash is keccak256(bytes(name))
        • versionHash is keccak256(bytes(version))
        • contractAddress is the proxy contract address
      • structHash is keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))
        • _TYPEHASH is keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)")
  3. '''Output''':

    • The result is a 32-byte array which is ready to be signed.

=== Signing the Transaction ===

The byte representation is then signed using the signer's NEO private key, utilizing the encryption methods described in NEP-2. The resulting signature is appended to the meta-transaction object.

  1. '''Signing Preparation''':

    • The signer's NEO private key should be decrypted (using methods from NEP-2 if necessary) and ready.
    • Use the byte representation from the previous step as input.
  2. '''Signature Process''':

    • Sign the byte representation using ECDSA or an equivalent algorithm supported by NEO with the signer's private key. A better solution is to use a deterministic signing process without random seed.
    • This results in a signature typically composed of two components: r and s, both fixed-size byte arrays.
  3. '''Appending the Signature''':

    • The resulting signature is attached to the meta-transaction object, usually in the format:
      ** r: First part of the signature.
      ** s: Second part of the signature.
    • Optionally, the v value, representing the recovery id, can also be appended if NEO's signing method requires it for recovery of the public key.

=== Verifying the Signature ===

The process for signature verification will be analogous to NEO's current transaction verification methodology. Extract the signature and public key from the meta-transaction object. Use the public key to verify that the signature matches the byte representation of the structured data.

  1. '''Extraction''':

    • Extract the r and s values (and v if provided) from the received meta-transaction.
    • If only the signature is provided, use the ECDSA recover method to obtain the signer's public key.
  2. '''Recreate Byte Representation''':

    • Serialize the structured data from the received meta-transaction to get its byte representation.
  3. '''Verification Process''':

    • Using ECDSA or the equivalent:
      ** Verify that the signature (r, s, and optionally v) matches the byte representation when checked against the signer's public key.
  4. '''Outcome''':

    • If successful, the meta-transaction is verified.
    • Otherwise, it's deemed invalid.

==Rationale==

Taking inspiration from Ethereum's EIP-712 and EIP-2771 as well as NEO's encryption methods in NEP-2, this proposal aims to combine best practices from both platforms. The design choices aim to enhance user experience, increase transparency, and ensure security. The structured data format was chosen for its clarity and ease of understanding, and the signing and verification methods are rooted in established cryptographic practices.

==Backwards Compatibility==

This proposal introduces a new format but doesn't alter any existing transaction formats on the NEO platform. Thus, it's backward compatible with the current infrastructure. Existing systems and wallets can choose to integrate this new format without any disruption to their ongoing operations.

==Test Cases==

Test cases will be crucial to ensure the correct implementation of the meta-transaction format, especially when it comes to signing and verification. These tests should cover various transaction scenarios, signature generations, and validation checks.

==Implementation==

Implementations will be based on the defined specification and rationale. They should adhere to the structured data format, signing method, and verification process detailed in the proposal. The implementation will be completed after community consensus on the specification.

== Security Considerations ==

  • '''Replay Attacks''': The nonce ensures that old meta-transactions can't be reused.
  • '''Phishing Attacks''': By making the data more human-readable, users are less likely to sign malicious transactions unknowingly.

@Hecate2
Copy link

Hecate2 commented Oct 20, 2023

Personally I do not think it is good for Neo to become another E-chain, and neither do I really love E-chains, but since Neo is testing EVM sidechain, I wrote a naive and unsafe ECrecover in csharp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants