From d5f1f9e10f7e1417ffa93fcb5f866fa1f2e95a37 Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 25 Mar 2018 19:24:41 +0200 Subject: [PATCH 1/7] copied EIP template to EIP 665 --- EIPS/eip-665.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 EIPS/eip-665.md diff --git a/EIPS/eip-665.md b/EIPS/eip-665.md new file mode 100644 index 00000000..e9460c69 --- /dev/null +++ b/EIPS/eip-665.md @@ -0,0 +1,45 @@ +--- +eip: +title: +author: +discussions-to: +status: Draft +type: +category (*only required for Standard Track): +created: +requires (*optional): +replaces (*optional): +--- + +This is the suggested template for new EIPs. + +Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. + +The title should be 44 characters or less. + +## Simple Summary +"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP. + +## Abstract +A short (~200 word) description of the technical issue being addressed. + +## Motivation +The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright. + +## Specification +The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (cpp-ethereum, go-ethereum, parity, ethereumj, ethereumjs, ...). + +## Rationale +The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion. + +## Backwards Compatibility +All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright. + +## Test Cases +Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable. + +## Implementation +The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From a70a025520292830a28e8755f05a71efd36f3e27 Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 25 Mar 2018 20:55:44 +0200 Subject: [PATCH 2/7] add proposal text --- EIPS/eip-665.md | 83 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/EIPS/eip-665.md b/EIPS/eip-665.md index e9460c69..e00f5b7f 100644 --- a/EIPS/eip-665.md +++ b/EIPS/eip-665.md @@ -1,45 +1,82 @@ --- -eip: -title: -author: -discussions-to: +eip: 665 +title: Add precompiled contract for Ed25519 signature verification +author: Tobias Oberstein status: Draft -type: -category (*only required for Standard Track): -created: -requires (*optional): -replaces (*optional): +type: Standards Track +category: Core +created: 2018-03-25 --- -This is the suggested template for new EIPs. - -Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. - -The title should be 44 characters or less. - ## Simple Summary -"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP. + +Support performant and cheap verification of Ed25519 cryptographic signatures in smart contracts in general by adding a precompiled contract for Ed25519 signature verification to the EVM. ## Abstract -A short (~200 word) description of the technical issue being addressed. + +Verification of Ed25519 cryptographic signatures is obviously possible in EVM bytecode. However, the gas cost will be very high, and computationally expensive, as such tight, wide word operations intensive code as required for Ed25519 is not a good fit for the EVM bytecode model. + +The addition of a native compiled function, in a precompiled contract, to the EVM solves both cost and performance problems. ## Motivation -The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright. + +One motivation for Ed25519 signature verification in smart contracts is to associate existing off-chain systems, records or accounts that use Ed25519 with blockchain transactions. + +Another motivation is the processing of external, Ed25519 proof-of-stake based blockchains within Ethereum smart contracts. + +When a transactions contains data that comes with an Ed25519 signature, that proves that the sender of the Ethereum transaction was also in control of the private key (and the data), and this allows the contract to establish an association between the blockchain and the external system or account, and the external system establish the reverse relation. + +For example, a contract might check a Ed25519 signed piece of data submitted to the Ethereum transaction like the current block number. That proves to the contract, that the sender is in possession of both the Ethereum private key and the Ed25518 private key, and hence the contract will accept an association between both. This again can be the root anchor for various powerful applications, as now a potentially crypto holding key owner has proven to be in control of some external off-chain system or account, like e.g. a DNS server, a DNS domain, a cluster node and so on. ## Specification -The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (cpp-ethereum, go-ethereum, parity, ethereumj, ethereumjs, ...). + +The proposal adds a new precompiled function with the following signature + +``` +ed25519verify(bytes32 m, bytes32 pk, bytes32 s1, bytes32 s2) returns (uint8) +``` + +The `ed25519verify` function takes as parameters: + +1. `m` (bytes32): The message that was signed. +2. `pk` (bytes32): The Ed25519 public key of the signer. +3. `s1` (bytes32): The first part of the 64-byte Ed25519 signature. +4. `s2` (bytes32): The second part of the 64-byte Ed25519 signature. + +The `ed25519verify` function returns zero if the signature was valid, and a non-zero value if the signature was invalid. ## Rationale -The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion. + +The proposed `ed25519verify` function takes the signer public key as a call parameter, as with Ed25519, I don't believe it is possible to derive the signers public key from the signature and message alone. + +The proposed `ed25519verify` function uses a zero return value to indicate success, since this allows for different errors to be distinguished by return value, as all non-zero return values signal a verification failure. ## Backwards Compatibility -All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright. + +The proposal is belived not to introduce any backward compatibility issues. ## Test Cases -Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable. + +Test vectors for Ed25519 can be found in this IETF ID https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-6. + +More test vectors can be found in the regression tests of NaCl (see references). ## Implementation -The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. + +NaCl is a high-quality implementation of Ed25519, available from the same team that created the algorithms and cryptography behind Ed25519. + +The library should allow implementations of the proposed `ed25519verify` function with few lines of code in the hosting Ethereum implementation. + +## References + +* Definition of Ed25519: https://ed25519.cr.yp.to/ed25519-20110926.pdf +* Ed25519 - high-speed high-security signatures: https://ed25519.cr.yp.to/ +* NaCl - Networking and Cryptography library: https://nacl.cr.yp.to/sign.html +* NaCl Crypto Libraries (which contains Ed25519): https://ianix.com/pub/ed25519-deployment.html +* Test vectors for Ed25519: https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-6 +* NaCl regression tests: https://ed25519.cr.yp.to/python/sign.py and https://ed25519.cr.yp.to/python/sign.input +* On the recoverability of public keys from signature+message (alone): https://crypto.stackexchange.com/questions/9936/what-signature-schemes-allow-recovering-the-public-key-from-a-signature ## Copyright + Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 3e9e531fd92f3922a57546ebf029ae2d93c402fb Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 25 Mar 2018 21:46:11 +0200 Subject: [PATCH 3/7] don't use function selectors, but direct input/output encoding in spec --- EIPS/eip-665.md | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/EIPS/eip-665.md b/EIPS/eip-665.md index e00f5b7f..9019c4c6 100644 --- a/EIPS/eip-665.md +++ b/EIPS/eip-665.md @@ -30,20 +30,27 @@ For example, a contract might check a Ed25519 signed piece of data submitted to ## Specification -The proposal adds a new precompiled function with the following signature +If `block.number >= CONSTANTINOPLE_FORK_BLKNUM`, add a precompiled contract for Ed25519 signature verification (`ED25519VFY`). -``` -ed25519verify(bytes32 m, bytes32 pk, bytes32 s1, bytes32 s2) returns (uint8) -``` +The proposal adds a new precompiled function `ED25519VFY` with the following input and output. -The `ed25519verify` function takes as parameters: +`ED25519VFY` takes as input 128 bytes: -1. `m` (bytes32): The message that was signed. -2. `pk` (bytes32): The Ed25519 public key of the signer. -3. `s1` (bytes32): The first part of the 64-byte Ed25519 signature. -4. `s2` (bytes32): The second part of the 64-byte Ed25519 signature. +1. **message**: The 32-byte message that was signed +2. **public key**: The 32-byte Ed25519 public key of the signer +3. **signature**: The 64-byte Ed25519 signature -The `ed25519verify` function returns zero if the signature was valid, and a non-zero value if the signature was invalid. +`ED25519VFY` returns as output 1 byte: + +1. **result**: `0x00` if signature is valid, else invalid signature + +### Address + +The address of `ED25519VFY` is `0x08`. + +### Gas costs + +Gas cost for `ED25519VFY` is 2000. ## Rationale @@ -51,9 +58,11 @@ The proposed `ed25519verify` function takes the signer public key as a call para The proposed `ed25519verify` function uses a zero return value to indicate success, since this allows for different errors to be distinguished by return value, as all non-zero return values signal a verification failure. +`ECRECOVER` has a gas cost of 3000. Since Ed25519 is computationally cheaper, the gas price should be less. + ## Backwards Compatibility -The proposal is belived not to introduce any backward compatibility issues. +As the proposed precompiled contract is deployed at a reserved (<255) and previously unused address, an implementation of the proposal should not introduce any backward compatibility issues. ## Test Cases From b8b5f87015e4883ecce4aa6c4f6da39ab20db1c7 Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Sun, 25 Mar 2018 21:49:30 +0200 Subject: [PATCH 4/7] cosmetics --- EIPS/eip-665.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EIPS/eip-665.md b/EIPS/eip-665.md index 9019c4c6..7e65055b 100644 --- a/EIPS/eip-665.md +++ b/EIPS/eip-665.md @@ -46,17 +46,17 @@ The proposal adds a new precompiled function `ED25519VFY` with the following inp ### Address -The address of `ED25519VFY` is `0x08`. +The address of `ED25519VFY` is **`0x8`.** ### Gas costs -Gas cost for `ED25519VFY` is 2000. +Gas cost for `ED25519VFY` is **2000**. ## Rationale -The proposed `ed25519verify` function takes the signer public key as a call parameter, as with Ed25519, I don't believe it is possible to derive the signers public key from the signature and message alone. +The proposed `ED25519VFY` function takes the signer public key as a call parameter, as with Ed25519, I don't believe it is possible to derive the signers public key from the signature and message alone. -The proposed `ed25519verify` function uses a zero return value to indicate success, since this allows for different errors to be distinguished by return value, as all non-zero return values signal a verification failure. +The proposed `ED25519VFY` function uses a zero return value to indicate success, since this allows for different errors to be distinguished by return value, as all non-zero return values signal a verification failure. `ECRECOVER` has a gas cost of 3000. Since Ed25519 is computationally cheaper, the gas price should be less. From 1dd71ebaf8d1f594ac55ffc2dc6076f37d1be300 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 26 Mar 2018 19:30:59 +0200 Subject: [PATCH 5/7] EIP-868: add sequence number to ping and pong --- EIPS/eip-868.md | 61 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/EIPS/eip-868.md b/EIPS/eip-868.md index 41732b42..5cfa2b48 100644 --- a/EIPS/eip-868.md +++ b/EIPS/eip-868.md @@ -18,35 +18,66 @@ resolution of Ethereum Node Records (ENR). To bridge current and future discovery networks and to aid the implementation of other relay mechanisms for ENR such as DNS, we need a way to request the most up-to-date version -of a node record. +of a node record. This EIP provides a way to request it using the existing discovery +protocol. # Specification -Implementations of Node Discovery Protocol v4 should support two new packet types, a request -and reply of the node record. The new packets are: +Implementations of Node Discovery Protocol v4 should support two new packet types, a +request and reply of the node record. The existing ping and pong packets are extended with +a new field containing the sequence number of the ENR. -### enrRequest (0x05) +### Ping Packet (0x01) -RLP: `[ expiration ]` +```text +packet-data = [version, from, to, expiration, enr-seq] +``` -When a packet of this type is received, the node should reply with an enrResponse packet +`enr-seq` is the current sequence number of the sending node's record. All other fields +retain their existing meaning. + +### Pong Packet (0x02) + +```text +packet-data = [to, ping-hash, expiration, enr-seq] +``` + +`enr-seq` is the current sequence number of the sending node's record. All other fields +retain their existing meaning. + +### ENRRequest Packet (0x05) + +```text +packet-data = [ expiration ] +``` + +When a packet of this type is received, the node should reply with an ENRResponse packet containing the current version of its record. -To guard against amplification attacks, the sender of enrRequest should have replied to a -ping packet recently. The expiration field, a UNIX timestamp, should be handled as for all -other existing packets, i.e. no reply should be sent if it refers to a time in the past. +To guard against amplification attacks, the sender of ENRRequest should have replied to a +ping packet recently (just like for FindNode). The `expiration` field, a UNIX timestamp, +should be handled as for all other existing packets i.e. no reply should be sent if it +refers to a time in the past. -### enrResponse (0x06) +### ENRResponse Packet (0x06) -RLP: `[ requestHash, ENR ]` +```text +packet-data = [ request-hash, ENR ] +``` -This packet is the response to enrRequest. +This packet is the response to ENRRequest. -- `requestHash` is the hash of the entire enrRequest packet being replied to. +- `request-hash` is the hash of the entire ENRRequest packet being replied to. - `ENR` is the node record. -The recipient of the packet should verify that the node record is signed by node who -sent enrResponse. +The recipient of the packet should verify that the node record is signed by node who sent +ENRResponse. + +## Resolving Records + +To resolve the current record of a node public key, perform a recursive Kademlia lookup +using the FindNode, Neighbors packets. When the node is found, send ENRRequest to it and +return the record from the response. # Copyright From 48bec76f5885098a571f21e545f7bba307972d25 Mon Sep 17 00:00:00 2001 From: John Forrest Date: Thu, 15 Mar 2018 17:09:22 -0500 Subject: [PATCH 6/7] Update operator language - Fixed typo (operator to operators) - Explicitly call out the implementation MUST support multiple operators per owner as implied by the comments - Removed unnecessary throw from the dev instructions on setApprovalForAll --- EIPS/eip-721.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-721.md b/EIPS/eip-721.md index 5b676469..50e530cc 100644 --- a/EIPS/eip-721.md +++ b/EIPS/eip-721.md @@ -60,7 +60,8 @@ interface ERC721 /* is ERC165 */ { event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. + /// The operator can manage all NFTs of the owner. The contract MUST allow + /// multiple operators per owner. event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @notice Count all NFTs assigned to an owner @@ -123,7 +124,7 @@ interface ERC721 /* is ERC165 */ { /// all of `msg.sender`'s assets. /// @dev Emits the ApprovalForAll event /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operators is approved, false to revoke approval + /// @param _approved True if the operator is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external; /// @notice Get the approved address for a single NFT From 87f1091c0cb2df961fbd8085cc56de8a039b2af6 Mon Sep 17 00:00:00 2001 From: John Forrest Date: Tue, 27 Mar 2018 10:48:17 -0500 Subject: [PATCH 7/7] Moving operator language to function instead of event --- EIPS/eip-721.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EIPS/eip-721.md b/EIPS/eip-721.md index 50e530cc..33579a82 100644 --- a/EIPS/eip-721.md +++ b/EIPS/eip-721.md @@ -60,8 +60,7 @@ interface ERC721 /* is ERC165 */ { event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. The contract MUST allow - /// multiple operators per owner. + /// The operator can manage all NFTs of the owner. event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @notice Count all NFTs assigned to an owner @@ -122,7 +121,8 @@ interface ERC721 /* is ERC165 */ { /// @notice Enable or disable approval for a third party ("operator") to manage /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event + /// @dev Emits the ApprovalForAll event. The contract MUST allow + /// multiple operators per owner. /// @param _operator Address to add to the set of authorized operators. /// @param _approved True if the operator is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external;