diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index 3661248a..d70d1092 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -5,10 +5,10 @@ Author: Martin Becze , Hudson Jameson Created: 2015-10-27, 2017-02-01 -What is a EIP? +What is an EIP? -------------- -EIP stands for Ethereum Improvement Proposal. A EIP is a design document providing information to the Ethereum community, or describing a new feature for Ethereum or its processes or environment. The EIP should provide a concise technical specification of the feature and a rationale for the feature. The EIP author is responsible for building consensus within the community and documenting dissenting opinions. +EIP stands for Ethereum Improvement Proposal. An EIP is a design document providing information to the Ethereum community, or describing a new feature for Ethereum or its processes or environment. The EIP should provide a concise technical specification of the feature and a rationale for the feature. The EIP author is responsible for building consensus within the community and documenting dissenting opinions. EIP Rational ------------ @@ -28,7 +28,7 @@ There are three types of EIP: - **Interface** - includes improvements around client [API/RPC] specifications and standards, and also certain language-level standards like method names ([EIP59], [EIP6]) and [contract ABIs]. The label “interface” aligns with the [interfaces repo] and discussion should primarily occur in that repository before an EIP is submitted to the EIPs repository. - **ERC** - application-level standards and conventions, including contract standards such as token standards ([ERC20]), name registries ([ERC26], [ERC137]), URI schemes ([ERC67]), library/package formats ([EIP82]), and wallet formats ([EIP75], [EIP85]). -- An **Informational EIP** describes a Ethereum design issue, or provides general guidelines or information to the Ethereum community, but does not propose a new feature. Informational EIPs do not necessarily represent Ethereum community consensus or a recommendation, so users and implementors are free to ignore Informational EIPs or follow their advice. +- An **Informational EIP** describes a Ethereum design issue, or provides general guidelines or information to the Ethereum community, but does not propose a new feature. Informational EIPs do not necessarily represent Ethereum community consensus or a recommendation, so users and implementers are free to ignore Informational EIPs or follow their advice. - A **Meta EIP** describes a process surrounding Ethereum or proposes a change to (or an event in) a process. Process EIPs are like Standards Track EIPs but apply to areas other than the Ethereum protocol itself. They may propose an implementation, but not to Ethereum's codebase; they often require community consensus; unlike Informational EIPs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Ethereum development. Any meta-EIP is also considered a Process EIP. EIP Work Flow @@ -40,21 +40,21 @@ The EIP process begins with a new idea for Ethereum. It is highly recommended th Each EIP must have a champion - someone who writes the EIP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. -Vetting an idea publicly before going as far as writing a EIP is meant to save the potential author time. Asking the Ethereum community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Ethereum is used. Examples of appropriate public forums to gauge interest around your EIP include [the Ethereum subreddit], [the Issues section of this repository], and [one of the Ethereum Gitter chat rooms]. In particular, [the Issues section of this repository] is an excellent place to discuss your proposal with the community and start creating more formalized language around your EIP. +Vetting an idea publicly before going as far as writing an EIP is meant to save the potential author time. Asking the Ethereum community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Ethereum is used. Examples of appropriate public forums to gauge interest around your EIP include [the Ethereum subreddit], [the Issues section of this repository], and [one of the Ethereum Gitter chat rooms]. In particular, [the Issues section of this repository] is an excellent place to discuss your proposal with the community and start creating more formalized language around your EIP. -Once the champion has asked the Ethereum community whether an idea has any chance of acceptance a draft EIP should be presented as a [pull request]. This gives the author a chance to coninuously edit the draft EIP for proper formatting and quality. This also allows for further public comment and the author of the EIP to address concerns about the proposal. +Once the champion has asked the Ethereum community whether an idea has any chance of acceptance a draft EIP should be presented as a [pull request]. This gives the author a chance to continuously edit the draft EIP for proper formatting and quality. This also allows for further public comment and the author of the EIP to address concerns about the proposal. -If the EIP collaborators approves, the EIP editor will assign the EIP a number (generally the issue or PR number related to the EIP), label it as Standards Track, Informational, or Meta, give it status “Draft”, and add it to the git repository. The EIP editor will not unreasonably deny an EIP. Reasons for denying EIP status include duplication of effort, being technically unsound, not providing proper motivation or addressing backwards compatibility, or not in keeping with the Ethereum philosophy. +If the EIP collaborators approve, the EIP editor will assign the EIP a number (generally the issue or PR number related to the EIP), label it as Standards Track, Informational, or Meta, give it status “Draft”, and add it to the git repository. The EIP editor will not unreasonably deny an EIP. Reasons for denying EIP status include duplication of effort, being technically unsound, not providing proper motivation or addressing backwards compatibility, or not in keeping with the Ethereum philosophy. Standards Track EIPs consist of three parts, a design document, implementation, and finally if warranted an update to the [formal specification]. The EIP should be reviewed and accepted before an implementation is begun, unless an implementation will aid people in studying the EIP. Standards Track EIPs must be implemented in at least three viable Ethereum clients before it can be considered Final. For an EIP to be accepted it must meet certain minimum criteria. It must be a clear and complete description of the proposed enhancement. The enhancement must represent a net improvement. The proposed implementation, if applicable, must be solid and must not complicate the protocol unduly. -Once a EIP has been accepted, the implementations must be completed. When the implementation is complete and accepted by the community, the status will be changed to “Final”. +Once an EIP has been accepted, the implementations must be completed. When the implementation is complete and accepted by the community, the status will be changed to “Final”. -A EIP can also be assigned status “Deferred”. The EIP author or editor can assign the EIP this status when no progress is being made on the EIP. Once a EIP is deferred, the EIP editor can re-assign it to draft status. +An EIP can also be assigned status “Deferred”. The EIP author or editor can assign the EIP this status when no progress is being made on the EIP. Once an EIP is deferred, the EIP editor can re-assign it to draft status. -A EIP can also be “Rejected”. Perhaps after all is said and done it was not a good idea. It is still important to have a record of this fact. +An EIP can also be “Rejected”. Perhaps after all is said and done it was not a good idea. It is still important to have a record of this fact. EIPs can also be superseded by a different EIP, rendering the original obsolete. @@ -145,7 +145,7 @@ if the email address is not given. Note: The Resolution header is required for Standards Track EIPs only. It contains a URL that should point to an email message or other web resource where the pronouncement about the EIP is made. -While a EIP is in private discussions (usually during the initial Draft phase), a Discussions-To header will indicate the mailing list or URL where the EIP is being discussed. No Discussions-To header is necessary if the EIP is being discussed privately with the author. +While an EIP is in private discussions (usually during the initial Draft phase), a Discussions-To header will indicate the mailing list or URL where the EIP is being discussed. No Discussions-To header is necessary if the EIP is being discussed privately with the author. The Type header specifies the type of EIP: Standards Track, Meta, or Informational. If the track is Standards please include the subcategory (core, networking, interface, or ERC). @@ -153,7 +153,7 @@ The Created header records the date that the EIP was assigned a number. Both hea EIPs may have a Requires header, indicating the EIP numbers that this EIP depends on. -EIPs may also have a Superseded-By header indicating that a EIP has been rendered obsolete by a later document; the value is the number of the EIP that replaces the current document. The newer EIP must have a Replaces header containing the number of the EIP that it rendered obsolete. +EIPs may also have a Superseded-By header indicating that an EIP has been rendered obsolete by a later document; the value is the number of the EIP that replaces the current document. The newer EIP must have a Replaces header containing the number of the EIP that it rendered obsolete. Auxiliary Files --------------- @@ -163,9 +163,9 @@ EIPs may include auxiliary files such as diagrams. Such files must be named EIP- Transferring EIP Ownership -------------------------- -It occasionally becomes necessary to transfer ownership of EIPs to a new champion. In general, we'd like to retain the original author as a co-author of the transferred EIP, but that's really up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the EIP process, or has fallen off the face of the 'net (i.e. is unreachable or not responding to email). A bad reason to transfer ownership is because you don't agree with the direction of the EIP. We try to build consensus around a EIP, but if that's not possible, you can always submit a competing EIP. +It occasionally becomes necessary to transfer ownership of EIPs to a new champion. In general, we'd like to retain the original author as a co-author of the transferred EIP, but that's really up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the EIP process, or has fallen off the face of the 'net (i.e. is unreachable or not responding to email). A bad reason to transfer ownership is because you don't agree with the direction of the EIP. We try to build consensus around an EIP, but if that's not possible, you can always submit a competing EIP. -If you are interested in assuming ownership of a EIP, send a message asking to take over, addressed to both the original author and the EIP editor. If the original author doesn't respond to email in a timely manner, the EIP editor will make a unilateral decision (it's not like such decisions can't be reversed :). +If you are interested in assuming ownership of an EIP, send a message asking to take over, addressed to both the original author and the EIP editor. If the original author doesn't respond to email in a timely manner, the EIP editor will make a unilateral decision (it's not like such decisions can't be reversed :). EIP Editors ----------- @@ -174,19 +174,13 @@ The current EIP editors are ` * Casey Detrio (@cdetrio)` -` * Fabian Vogelsteller (@frozeman)` - -` * Gavin Wood (@gavofyork)` - ` * Hudson Jameson (@Souptacular)` -` * Jeffrey Wilcke (@obscuren)` - ` * Martin Becze (@wanderer)` ` * Nick Johnson (@arachnid)` -` * Roman Mandeleil (@romanman)` +` * Yoichi Hirai (@pirapira)` ` * Vitalik Buterin (@vbuterin)` @@ -203,7 +197,7 @@ If the EIP isn't ready, the editor will send it back to the author for revision, Once the EIP is ready for the repository, the EIP editor will: -- Assign a EIP number (generally the PR number or, if preferred by the author, the Issue # if ther was discussion in the Issues section of this repository about this EIP) +- Assign an EIP number (generally the PR number or, if preferred by the author, the Issue # if there was discussion in the Issues section of this repository about this EIP) @@ -237,7 +231,7 @@ February 1, 2016: EIP 1 has added editors, made draft improvements to process, a [devp2p]: https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol [EIP8]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md [Light Ethereum Subprotocol]: https://github.com/ethereum/wiki/wiki/Light-client-protocol - [whisper]: https://gist.github.com/gluk256/4654922ca45eb9d0846d941d7ca326f4 + [whisper]: https://github.com/ethereum/go-ethereum/wiki/Whisper-Overview [swarm]: https://github.com/ethereum/go-ethereum/pull/2959 [API/RPC]: https://github.com/ethereum/wiki/wiki/JSON-RPC [EIP59]: https://github.com/ethereum/EIPs/issues/59 diff --git a/EIPS/eip-100.md b/EIPS/eip-100.md new file mode 100644 index 00000000..6bb6dcfc --- /dev/null +++ b/EIPS/eip-100.md @@ -0,0 +1,39 @@ +``` +EIP: 100 +Title: Change difficulty adjustment to target mean block time including uncles +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Accepted +Created: 2016-04-28 +``` + +### Specification + +Currently, the formula to compute the difficulty of a block includes the following logic: + +``` python +adj_factor = max(1 - ((timestamp - parent.timestamp) // 10), -99) +child_diff = int(max(parent.difficulty + (parent.difficulty // BLOCK_DIFF_FACTOR) * adj_factor, min(parent.difficulty, MIN_DIFF))) +... +``` + +If `block.number >= BYZANTIUM_FORK_BLKNUM`, we change the first line to the following: + +``` python +adj_factor = max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) +``` +### Rationale + +This new formula ensures that the difficulty adjustment algorithm targets a constant average rate of blocks produced including uncles, and so ensures a highly predictable issuance rate that cannot be manipulated upward by manipulating the uncle rate. A formula that accounts for the exact number of included uncles: +``` python +adj_factor = max(1 + len(parent.uncles) - ((timestamp - parent.timestamp) // 9), -99) +``` +can be fairly easily seen to be (to within a tolerance of ~3/4194304) mathematically equivalent to assuming that a block with `k` uncles is equivalent to a sequence of `k+1` blocks that all appear with the exact same timestamp, and this is likely the simplest possible way to accomplish the desired effect. But since the exact formula depends on the full block and not just the header, we are instead using an approximate formula that accomplishes almost the same effect but has the benefit that it depends only on the block header (as you can check the uncle hash against the blank hash). + +Changing the denominator from 10 to 9 ensures that the block time remains roughly the same (in fact, it should decrease by ~3% given the current uncle rate of 7%). + +### References + +1. EIP 100 issue and discussion: https://github.com/ethereum/EIPs/issues/100 +2. https://bitslog.wordpress.com/2016/04/28/uncle-mining-an-ethereum-consensus-protocol-flaw/ diff --git a/EIPS/eip-107.md b/EIPS/eip-107.md new file mode 100644 index 00000000..2054368a --- /dev/null +++ b/EIPS/eip-107.md @@ -0,0 +1,614 @@ +
+  EIP: 107
+  Title: safe "eth_sendTransaction" authorization via html popup
+  Author: Ronan Sandford 
+  Created: 2016-06-05
+  Status: Draft
+  Type: Standard
+  Category: Interface
+
+ +Abstract +======== +This draft EIP describes the details of an authorization method that if provided by rpc enabled ethereum nodes would allow regular websites to send transactions (via ```eth_sendTransaction```) without the need to enable CORS. Instead, user would be asked to confirm the transaction via an html popup. + +Every read only rpc call the dapp wants to perform is redirected to an invisible iframe from the node's domain and for every transaction that the dapp wish to execute, an html popup is presented to the user to allow him/her to cancel or confirm the transaction. This allows the dapp to connect to the node's rpc api without being granted any kind of privileges. This allows users to safely interact with dapps running in their everyday web browser while their accounts are unlocked. In case the account is not unlocked, and the node has allowed the "personal" api via rpc,the html page also allow the user to enter their password to unlock the account for the scope of the transaction. + +Motivation +========== +Currently, if a user navigates to a dapp running on a website using her/his everyday browser, the dapp will by default have no access to the rpc api for security reasons. The user will have to enable CORS for the website's domain in order for the dapp to work. Unfortunately if the user does so, the dapp will be able to send transactions from any unlocked account without the need for any user consent. In other words, not only does the user need to change the node's default setting, but the user is also forced to trust the dapp in order to use it. This is of course not acceptable and forces existing dapps to rely on the use of workarrounds like: +- if the transaction is a plain ether transfer, the user is asked to enter it in a dedicated trusted wallet like "Mist" +- For more complex case, the user is asked to enter the transaction manually via the node command line interface. + + +This proposal aims to provide a safe and user friendly alternative. + +Here are some screenshots of the provided implementation of that html popup: + +Account unlocked : +----------------- +When the account is already unlocked, the user is presented with the following popup for every transaction that the dapp attempts to make: + + + +Account locked and no "personal" api exposed via rpc: +----------------- +When the account is locked, and the node does not provide access to account unlocking via its rpc interface, the following popup will be presented. This is not ideal since this requires the user to know how to unlock an account: + + + +Account locked but node exposing the "personal" api via rpc : +----------------- +A better option is to ask the user for their password, but this is only possible if the node allows access to the "personal" api via rpc. In such case, the following dialog will be presented to the user so he/she can accept the transaction by providing the password required to unlock the account: + + + + +Specification +============= +In order for the mechanism to work, the node needs to serve an html file via http at the url \/authorization.html + +This file will then be used by the dapp in 2 different modes (invisible iframe and popup window). + +The invisible iframe will be embeded in the dapp to allow the dapp to send its read-only rpc call without having to enable CORS for the dapp's website domain. This is done by sending message to the iframe (via javascript ```window.postMessage```) which in turn execute the rpc call. This works since the iframe and the node share the same domain/port. + +In the iframe mode, the html file's javascript code will ensure that no call requiring an unlocked key can be made. This is to prevent dapps from embedding the invisible iframe and tricking the user into clicking the confirm button. +If the dapp requires an ```eth_sendTransaction``` call, the dapp will instead open a new window using the same url. + +In this popup window mode, the html file's javascript code will alow ```eth_sendTransaction``` (but not ```eth_sign```, as there is no way to display to the user the meaningful content of the transaction to sign in a safe way) to be called. But instead of sending the call to the node directly, a confirmation dialog will be presented showing the sender and recipient addresses, as well as the amount being transfered along with the potential gas cost. Upon the user approving, the request will be sent and the result returned to the dapp. An error will be returned in case the user cancel the request. + +The html page also checks for the availability of the "personal" api and if so, will ask the user to unlock the account if necessary. The unlocking is temporary (3s) so the password will be asked again if a transaction is attempted before the end of this short time. + +In both iframe mode and window mode, the communication with the dapp is achieved using ```window.postMessage```. +The fist message the iframe/window sends is a message containing the string "ready" to let the dapp know that it now accepts messages. Then the dapp can start performing rpc call by sending message using the following object : +``` +{ + id:, //so responses can be match as there is no guarantee of the order of the response + payload: //this is the exact object that usually send to the node +} +``` + +For ```eth_sendTransaction``` the "gas", "gasPrice" and "from" field need to be set in the rpc parameter so that the window can display the correct value. If not all of these are passed in, the window will return an error. + +Upon receiving such message, the iframe will perform the actual rpc call to the node but only if such a call is a read only call (not requiring an unlocked key). If it is not it will return a error. The window on the other will only accept ```eth_sendTransaction``` calls but will display a dialog so the user can accept or cancel the request. + +In all the cases, the iframe/window will send a message back to the dapp using the following object: +``` +{ + id:, + result:, + error: +} +``` + +the error object cannot be a javascript Error object due to postMessage limitation. Instead it is +``` +{ + message:, + type: //type="cancel" means the user cancel the transaction +} +``` + + +Rationale +========= +The design for that proposal was chosen for its simplicity and security. A previous idea was to use an oauth-like protocol in order for the user to accept or deny a transaction request. It would have required deeper code change in the node and some geth contributors argues that such change did not fit into geth code base as it would have required dapp aware code. +The current design, instead has a very simple implementation (self contained html file that can be shared across node's implementation) and its safeness is guarantess by browsers' cross domain policies. + +The use of iframe/ window was required to have both security and user friendliness. The invisble iframe allows the dapp to execute read only calls without the need for user input, and the window ensures user approval before making a call. While we could have made it without the window mode by making the iframe confirmation use the native browser ```window.confirm``` dialog, this would have prevented the use of a more elegant confirmation popup that the current design allows. It also happens to be that the ```window.confirm``` is not safe in some browsers, as it gives focus to the accept option and can be triggered automatically (https://bugs.chromium.org/p/chromium/issues/detail?id=260653). + + +Implementations +=============== +In order to implement this design, the following html file or an equivalent one needs to be served at the url \/authorization.html + +That's it. + + +``` + + + + Ethereum Authorization + + + + + + + +
+
+

Please wait...

+
+ +
+
+

+

+ + +
+ + + + + + +``` diff --git a/EIPS/eip-107/authorization-locked.png b/EIPS/eip-107/authorization-locked.png new file mode 100644 index 00000000..4f881bca Binary files /dev/null and b/EIPS/eip-107/authorization-locked.png differ diff --git a/EIPS/eip-107/authorization-password.png b/EIPS/eip-107/authorization-password.png new file mode 100644 index 00000000..32b91197 Binary files /dev/null and b/EIPS/eip-107/authorization-password.png differ diff --git a/EIPS/eip-107/authorization.png b/EIPS/eip-107/authorization.png new file mode 100644 index 00000000..b7dc9ae0 Binary files /dev/null and b/EIPS/eip-107/authorization.png differ diff --git a/EIPS/eip-137.md b/EIPS/eip-137.md new file mode 100644 index 00000000..b28b6fd3 --- /dev/null +++ b/EIPS/eip-137.md @@ -0,0 +1,386 @@ +
+  EIP: 137
+  Title: Ethereum Domain Name Service - Specification
+  Author: Nick Johnson 
+  Status: Final
+  Type: Standards Track
+  Category: ERC
+  Created: 2016-04-04
+
+ +# Abstract + +This draft EIP describes the details of the Ethereum Name Service, a proposed protocol and ABI definition that provides flexible resolution of short, human-readable names to service and resource identifiers. This permits users and developers to refer to human-readable and easy to remember names, and permits those names to be updated as necessary when the underlying resource (contract, content-addressed data, etc) changes. + +The goal of domain names is to provide stable, human-readable identifiers that can be used to specify network resources. In this way, users can enter a memorable string, such as 'vitalik.wallet' or 'www.mysite.swarm', and be directed to the appropriate resource. The mapping between names and resources may change over time, so a user may change wallets, a website may change hosts, or a swarm document may be updated to a new version, without the domain name changing. Further, a domain need not specify a single resource; different record types allow the same domain to reference different resources. For instance, a browser may resolve 'mysite.swarm' to the IP address of its server by fetching its A (address) record, while a mail client may resolve the same address to a mail server by fetching its MX (mail exchanger) record. +# Motivation + +Existing [specifications](https://github.com/ethereum/wiki/wiki/Registrar-ABI) and [implementations](https://ethereum.gitbooks.io/frontier-guide/content/registrar_services.html) for name resolution in Ethereum provide basic functionality, but suffer several shortcomings that will significantly limit their long-term usefulness: +- A single global namespace for all names with a single 'centralised' resolver. +- Limited or no support for delegation and sub-names/sub-domains. +- Only one record type, and no support for associating multiple copies of a record with a domain. +- Due to a single global implementation, no support for multiple different name allocation systems. +- Conflation of responsibilities: Name resolution, registration, and whois information. + +Use-cases that these features would permit include: +- Support for subnames/sub-domains - eg, live.mysite.tld and forum.mysite.tld. +- Multiple services under a single name, such as a DApp hosted in Swarm, a Whisper address, and a mail server. +- Support for DNS record types, allowing blockchain hosting of 'legacy' names. This would permit an Ethereum client such as Mist to resolve the address of a traditional website, or the mail server for an email address, from a blockchain name. +- DNS gateways, exposing ENS domains via the Domain Name Service, providing easier means for legacy clients to resolve and connect to blockchain services. + +The first two use-cases, in particular, can be observed everywhere on the present-day internet under DNS, and we believe them to be fundamental features of a name service that will continue to be useful as the Ethereum platform develops and matures. + +The normative parts of this document does not specify an implementation of the proposed system; its purpose is to document a protocol that different resolver implementations can adhere to in order to facilitate consistent name resolution. An appendix provides sample implementations of resolver contracts and libraries, which should be treated as illustrative examples only. + +Likewise, this document does not attempt to specify how domains should be registered or updated, or how systems can find the owner responsible for a given domain. Registration is the responsibility of registrars, and is a governance matter that will necessarily vary between top-level domains. + +Updating of domain records can also be handled separately from resolution. Some systems, such as swarm, may require a well defined interface for updating domains, in which event we anticipate the development of a standard for this. +# Specification +## Overview + +The ENS system comprises three main parts: +- The ENS registry +- Resolvers +- Registrars + +The registry is a single contract that provides a mapping from any registered name to the resolver responsible for it, and permits the owner of a name to set the resolver address, and to create subdomains, potentially with different owners to the parent domain. + +Resolvers are responsible for performing resource lookups for a name - for instance, returning a contract address, a content hash, or IP address(es) as appropriate. The resolver specification, defined here and extended in other EIPs, defines what methods a resolver may implement to support resolving different types of records. + +Registrars are responsible for allocating domain names to users of the system, and are the only entities capable of updating the ENS; the owner of a node in the ENS registry is its registrar. Registrars may be contracts or externally owned accounts, though it is expected that the root and top-level registrars, at a minimum, will be implemented as contracts. + +Resolving a name in ENS is a two-step process. First, the ENS registry is called with the name to resolve, after hashing it using the procedure described below. If the record exists, the registry returns the address of its resolver. Then, the resolver is called, using the method appropriate to the resource being requested. The resolver then returns the desired result. + +For example, suppose you wish to find the address of the token contract associated with 'beercoin.eth'. First, get the resolver: + +``` +var node = namehash("beercoin.eth"); +var resolver = ens.resolver(node); +``` + +Then, ask the resolver for the address for the contract: + +``` +var hash = resolver.addr(node); +``` + +Because the `namehash` procedure depends only on the name itself, this can be precomputed and inserted into a contract, removing the need for string manipulation, and permitting O(1) lookup of ENS records regardless of the number of components in the raw name. +## Name Syntax + +ENS names must conform to the following syntax: + +
<domain> ::= <label> | <domain> "." <label>
+<label> ::= any valid string label per [UTS46](http://unicode.org/reports/tr46/)
+
+ +In short, names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](http://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. + +Note that while upper and lower case letters are allowed in names, the UTS46 normalisation process case-folds labels before hashing them, so two names with different case but identical spelling will produce the same namehash. + +Labels and domains may be of any length, but for compatibility with legacy DNS, it is recommended that labels be restricted to no more than 64 characters each, and complete ENS names to no more than 255 characters. For the same reason, it is recommended that labels do not start or end with hyphens, or start with digits. + +## namehash algorithm + +Before being used in ENS, names are hashed using the 'namehash' algorithm. This algorithm recursively hashes components of the name, producing a unique, fixed-length string for any valid input domain. The output of namehash is referred to as a 'node'. + +Pseudocode for the namehash algorithm is as follows: + +``` +def namehash(name): + if name == '': + return '\0' * 32 + else: + label, _, remainder = name.partition('.') + return sha3(namehash(remainder) + sha3(label)) +``` + +Informally, the name is split into labels, each label is hashed. Then, starting with the last component, the previous output is concatenated with the label hash and hashed again. The first component is concatenated with 32 '0' bytes. Thus, 'mysite.swarm' is processed as follows: + +``` +node = '\0' * 32 +node = sha3(node + sha3('swarm')) +node = sha3(node + sha3('mysite')) +``` + +Implementations should conform to the following test vectors for namehash: + + namehash('') = 0x0000000000000000000000000000000000000000000000000000000000000000 + namehash('eth') = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae + namehash('foo.eth') = 0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f + +## Registry specification + +The ENS registry contract exposes the following functions: + +``` +function owner(bytes32 node) constant returns (address); +``` + +Returns the owner (registrar) of the specified node. + +``` +function resolver(bytes32 node) constant returns (address); +``` + +Returns the resolver for the specified node. + +``` +function ttl(bytes32 node) constant returns (uint64); +``` + +Returns the time-to-live (TTL) of the node; that is, the maximum duration for which a node's information may be cached. + +``` +function setOwner(bytes32 node, address owner); +``` + +Transfers ownership of a node to another registrar. This function may only be called by the current owner of `node`. A successful call to this function logs the event `Transfer(bytes32 indexed, address)`. + +``` +function setSubnodeOwner(bytes32 node, bytes32 label, address owner); +``` + +Creates a new node, `sha3(node, label)` and sets its owner to `owner`, or updates the node with a new owner if it already exists. This function may only be called by the current owner of `node`. A successful call to this function logs the event `NewOwner(bytes32 indexed, bytes32 indexed, address)`. + +``` +function setResolver(bytes32 node, address resolver); +``` + +Sets the resolver address for `node`. This function may only be called by the owner of `node`. A successful call to this function logs the event `NewResolver(bytes32 indexed, address)`. + +``` +function setTTL(bytes32 node, uint64 ttl); +``` + +Sets the TTL for a node. A node's TTL applies to the 'owner' and 'resolver' records in the registry, as well as to any information returned by the associated resolver. +## Resolver specification + +Resolvers may implement any subset of the record types specified here. Where a record types specification requires a resolver to provide multiple functions, the resolver MUST implement either all or none of them. Resolvers MUST specify a fallback function that throws. + +Resolvers have one mandatory function: + +``` +function supportsInterface(bytes4 interfaceID) constant returns (bool) +``` + +The `supportsInterface` function is documented in [EIP 165](https://github.com/ethereum/EIPs/issues/165), and returns true if the resolver implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a resolver returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. + +`supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself. + + Currently standardised resolver interfaces are specified in the table below. + +The following interfaces are defined: + +| Interface name | Interface hash | Specification | +| --- | --- | --- | +| `addr` | 0x3b3b57de | [Contract address](#addr) | +| `name` | 0x691f3431 | #181 | +| `ABI` | 0x2203ab56 | #205 | +| `pubkey` | 0xc8690233 | #619 | + +EIPs may define new interfaces to be added to this registry. + +###
Contract Address Interface + +Resolvers wishing to support contract address resources must provide the following function: + +``` +function addr(bytes32 node) constant returns (address); +``` + +If the resolver supports `addr` lookups but the requested node does not have a record, the resolver MUST return the zero address. + +Clients resolving the `addr` record MUST check for a zero return value, and treat this in the same manner as a name that does not have a resolver specified - that is, refuse to send funds to or interact with the address. Failure to do this can result in users accidentally sending funds to the 0 address. + +Changes to an address MUST trigger the following event: + +``` +event AddrChanged(bytes32 indexed node, address a); +``` +# Appendix A: Registry Implementation + +``` +contract ENS { + struct Record { + address owner; + address resolver; + uint64 ttl; + } + + mapping(bytes32=>Record) records; + + event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); + event Transfer(bytes32 indexed node, address owner); + event NewResolver(bytes32 indexed node, address resolver); + + modifier only_owner(bytes32 node) { + if(records[node].owner != msg.sender) throw; + _ + } + + function ENS(address owner) { + records[0].owner = owner; + } + + function owner(bytes32 node) constant returns (address) { + return records[node].owner; + } + + function resolver(bytes32 node) constant returns (address) { + return records[node].resolver; + } + + function ttl(bytes32 node) constant returns (uint64) { + return records[node].ttl; + } + + function setOwner(bytes32 node, address owner) only_owner(node) { + Transfer(node, owner); + records[node].owner = owner; + } + + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) { + var subnode = sha3(node, label); + NewOwner(node, label, owner); + records[subnode].owner = owner; + } + + function setResolver(bytes32 node, address resolver) only_owner(node) { + NewResolver(node, resolver); + records[node].resolver = resolver; + } + + function setTTL(bytes32 node, uint64 ttl) only_owner(node) { + NewTTL(node, ttl); + records[node].ttl = ttl; + } +} +``` +# Appendix B: Sample Resolver Implementations +### Built-in resolver + +The simplest possible resolver is a contract that acts as its own name resolver by implementing the contract address resource profile: + +``` +contract DoSomethingUseful { + // Other code + + function addr(bytes32 node) constant returns (address) { + return this; + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` + +Such a contract can be inserted directly into the ENS registry, eliminating the need for a separate resolver contract in simple use-cases. However, the requirement to 'throw' on unknown function calls may interfere with normal operation of some types of contract. + +### Standalone resolver + +A basic resolver that implements the contract address profile, and allows only its owner to update records: + +``` +contract Resolver { + event AddrChanged(bytes32 indexed node, address a); + + address owner; + mapping(bytes32=>address) addresses; + + modifier only_owner() { + if(msg.sender != owner) throw; + _ + } + + function Resolver() { + owner = msg.sender; + } + + function addr(bytes32 node) constant returns(address) { + return addresses[node]; + } + + function setAddr(bytes32 node, address addr) only_owner { + addresses[node] = addr; + AddrChanged(node, addr); + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` + +After deploying this contract, use it by updating the ENS registry to reference this contract for a name, then calling `setAddr()` with the same node to set the contract address it will resolve to. +### Public resolver + +Similar to the resolver above, this contract only supports the contract address profile, but uses the ENS registry to determine who should be allowed to update entries: + +``` +contract PublicResolver { + event AddrChanged(bytes32 indexed node, address a); + event ContentChanged(bytes32 indexed node, bytes32 hash); + + ENS ens; + mapping(bytes32=>address) addresses; + + modifier only_owner(bytes32 node) { + if(ens.owner(node) != msg.sender) throw; + _ + } + + function PublicResolver(address ensAddr) { + ens = ENS(ensAddr); + } + + function addr(bytes32 node) constant returns (address ret) { + ret = addresses[node]; + } + + function setAddr(bytes32 node, address addr) only_owner(node) { + addresses[node] = addr; + AddrChanged(node, addr); + } + + function supportsInterface(bytes4 interfaceID) constant returns (bool) { + return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7; + } + + function() { + throw; + } +} +``` +# Appendix C: Sample Registrar Implementation + +This registrar allows users to register names at no cost if they are the first to request them. + +``` +contract FIFSRegistrar { + ENS ens; + bytes32 rootNode; + + function FIFSRegistrar(address ensAddr, bytes32 node) { + ens = ENS(ensAddr); + rootNode = node; + } + + function register(bytes32 subnode, address owner) { + var node = sha3(rootNode, subnode); + var currentOwner = ens.owner(node); + if(currentOwner != 0 && currentOwner != msg.sender) + throw; + + ens.setSubnodeOwner(rootNode, subnode, owner); + } +} +``` diff --git a/EIPS/eip-141.md b/EIPS/eip-141.md new file mode 100644 index 00000000..f1346380 --- /dev/null +++ b/EIPS/eip-141.md @@ -0,0 +1,29 @@ +## Preamble + + EIP: 141 + Title: Designated invalid EVM instruction + Author: Alex Beregszaszi + Type: Standard Track + Category: Core + Status: Accepted + Created: 2017-02-09 + +## Abstract + +An instruction is designated to remain as an invalid instruction. + +## Motivation + +The invalid instruction can be used as a distinct reason to abort execution. + +## Specification + +The opcode `0xfe` is the `INVALID` instruction. It can be used to abort the execution (i.e. duplicates as an `ABORT` instruction). + +## Backwards Compatibility + +This instruction was never used and therefore has no effect on past contracts. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-145.md b/EIPS/eip-145.md new file mode 100644 index 00000000..6cd270c3 --- /dev/null +++ b/EIPS/eip-145.md @@ -0,0 +1,94 @@ +## Preamble + + EIP: 145 + Title: Bitwise shifting instructions in EVM + Author: Alex Beregszaszi, Paweł Bylica + Type: Standard Track + Category: Core + Status: Final + Created: 2017-02-13 + + +## Simple Summary + +To provide native bitwise shifting with cost on par with other arithmetic operations. + +## Abstract + +Native bitwise shifting instructions are introduced, which are more efficient processing wise on the host and are cheaper to use by a contract. + +## Motivation + +EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetics cost each 35 gas, while the proposed instructions take 3 gas. + +## Specification + +The following instructions are introduced: + +### `0x1b`: `SHL` (shift left) + +The `SHL` instruction (shift left) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the left by `arg1` number of bits. The result is equal to + +``` +(arg2 * 2^arg1) mod 2^256 +``` + +Notes: +- The value (`arg2`) is interpreted as an unsigned number. +- The shift amount (`arg1`) is interpreted as an unsigned number. +- If the shift amount (`arg1`) is greater or equal 256 the result is 0. +- This is equivalent to `PUSH1 2 EXP MUL`. + +### `0x1c`: `SHR` (logical shift right) + +The `SHR` instruction (logical shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with zero fill. The result is equal to + +``` +floor(arg2 / 2^arg1) +``` + +Notes: +- The value (`arg2`) is interpreted as an unsigned number. +- The shift amount (`arg1`) is interpreted as an unsigned number. +- If the shift amount (`arg1`) is greater or equal 256 the result is 0. +- This is equivalent to `PUSH1 2 EXP DIV`. + +### `0x1d`: `SAR` (arithmetic shift right) + +The `SAR` instruction (arithmetic shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with sign extension. The result is equal to + +``` +floor(arg2 / 2^arg1) +``` + +Notes: +- The value (`arg2`) is interpreted as a signed number. +- The shift amount (`arg1`) is interpreted as an unsigned number. +- If the shift amount (`arg1`) is greater or equal 256 the result is 0 if `arg2` is non-negative or -1 if `arg2` is negative. +- This is **not** equivalent to `PUSH1 2 EXP SDIV`, since it rounds differently. See `SDIV(-1, 2) == 0`, while `SAR(-1, 1) == -1`. + +The cost of the shift instructions is set at `verylow` tier (3 gas). + +## Rationale + +Instruction operands were chosen to fit the more natural use case of shifting a value already on the stack. This means the operand order is swapped compared to most arithmetic insturctions. + +## Backwards Compatibility + +The newly introduced instructions have no effect on bytecode created in the past. + +## Test Cases + +TBA + +## Implementation + +Client support: +- cpp-ethereum: https://github.com/ethereum/cpp-ethereum/pull/4054 + +Compiler support: +- Solidity/LLL: https://github.com/ethereum/solidity/pull/2541 + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md new file mode 100644 index 00000000..012f76e3 --- /dev/null +++ b/EIPS/eip-150.md @@ -0,0 +1,59 @@ +## Preamble +``` +EIP: 150 +Title: Gas cost changes for IO-heavy operations +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Final +Created: 2016-09-24 +``` + +### Specification + +If `block.number >= FORK_BLKNUM`, then: +- Increase the gas cost of EXTCODESIZE to 700 +- Increase the base gas cost of EXTCODECOPY to 700 +- Increase the gas cost of BALANCE to 400 +- Increase the gas cost of SLOAD to 200 +- Increase the gas cost of CALL, DELEGATECALL, CALLCODE to 700 +- Increase the gas cost of SELFDESTRUCT to 5000 +- If SELFDESTRUCT hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) +- Increase the recommended gas limit target to 5.5 million +- Define "all but one 64th" of `N` as `N - floor(N / 64)` +- If a call asks for more gas than the maximum allowed amount (ie. total amount of gas remaining in the parent after subtracting the gas cost of the call and memory expansion), do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. + +That is, substitute: + +``` + extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ + (value > 0) * opcodes.GCALLVALUETRANSFER + if compustate.gas < gas + extra_gas: + return vm_exception('OUT OF GAS', needed=gas+extra_gas) + submsg_gas = gas + opcodes.GSTIPEND * (value > 0) +``` + +With: + +``` + def max_call_gas(gas): + return gas - (gas // 64) + + extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ + (value > 0) * opcodes.GCALLVALUETRANSFER + if compustate.gas < extra_gas: + return vm_exception('OUT OF GAS', needed=extra_gas) + if compustate.gas < gas + extra_gas: + gas = min(gas, max_call_gas(compustate.gas - extra_gas)) + submsg_gas = gas + opcodes.GSTIPEND * (value > 0) +``` + +### Rationale + +Recent denial-of-service attacks have shown that opcodes that read the state tree are under-priced relative to other opcodes. There are software changes that have been made, are being made and can be made in order to mitigate the situation; however, the fact will remain that such opcodes will be by a substantial margin the easiest known mechanism to degrade network performance via transaction spam. The concern arises because it takes a long time to read from disk, and is additionally a risk to future sharding proposals as the "attack transactions" that have so far been most successful in degrading network performance would also require tens of megabytes to provide Merkle proofs for. This EIP increases the cost of storage reading opcodes to address this concern. The costs have been derived from an updated version of the calculation table used to generate the 1.0 gas costs: https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0 ; the rules attempt to target a limit of 8 MB of data that needs to be read in order to process a block, and include an estimate of 500 bytes for a Merkle proof for SLOAD and 1000 for an account. + +This EIP aims to be simple, and adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code (~17-21 kb in the worst case). + +The EIP 90 gas mechanic is introduced because without it, all current contracts that make calls would stop working as they use an expression like `msg.gas - 40` to determine how much gas to make a call with, relying on the gas cost of calls being 40. Additionally, EIP 114 is introduced because, given that we are making the cost of a call higher and less predictable, we have an opportunity to do it at no extra cost to currently available guarantees, and so we also achieve the benefit of replacing the call stack depth limit with a "softer" gas-based restriction, thereby eliminating call stack depth attacks as a class of attack that contract developers have to worry about and hence increasing contract programming safety. Note that with the given parameters, the de-facto maximum call stack depth is limited to ~340 (down from ~1024), mitigating the harm caused by any further potential quadratic-complexity DoS attacks that rely on calls. + +The gas limit increase is recommended so as to preserve the de-facto transactions-per-second processing capability of the system for average contracts. diff --git a/EIPS/eip-155.md b/EIPS/eip-155.md new file mode 100644 index 00000000..869a842e --- /dev/null +++ b/EIPS/eip-155.md @@ -0,0 +1,63 @@ +## Preamble +``` +EIP: 155 +Title: Simple replay attack protection +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Final +Created: 2016-10-14 +``` + +### Parameters +- `FORK_BLKNUM`: TBA +- `CHAIN_ID`: 1 +### Specification + +If `block.number >= FORK_BLKNUM` and `v = CHAIN_ID * 2 + 35` or `v = CHAIN_ID * 2 + 36`, then when computing the hash of a transaction for purposes of signing or recovering, instead of hashing only the first six elements (ie. nonce, gasprice, startgas, to, value, data), hash nine elements, with `v` replaced by `CHAIN_ID`, `r = 0` and `s = 0`. The currently existing signature scheme using `v = 27` and `v = 28` remains valid and continues to operate under the same rules as it does now. +### Example + +Consider a transaction with `nonce = 9`, `gasprice = 20 * 10**9`, `startgas = 21000`, `to = 0x3535353535353535353535353535353535353535`, `value = 10**18`, `data=''` (empty). + +The "signing data" becomes: + +``` +0xec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080 +``` + +The "signing hash" becomes: + +``` +0xdaf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53 +``` + +If the transaction is signed with the private key `0x4646464646464646464646464646464646464646464646464646464646464646`, then the v,r,s values become: + +``` +(37, 18515461264373351373200002665853028612451056578545711640558177340181847433846, 46948507304638947509940763649030358759909902576025900602547168820602576006531) +``` + +Notice the use of 37 instead of 27. The signed tx would become: + +``` +0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83 +``` +### Rationale + +This would provide a way to send transactions that work on ethereum without working on ETC or the Morden testnet. ETC is encouraged to adopt this EIP but replacing `CHAIN_ID` with a different value, and all future testnets, consortium chains and alt-etherea are encouraged to adopt this EIP replacing `CHAIN_ID` with a unique value. + + +### List of Chain ID's: + +| `CHAIN_ID` | Chain(s) | +| ---------------| -------------------------------------------| +| 1 | Ethereum mainnet | +| 2 | Morden (disused), Expanse mainnet | +| 3 | Ropsten | +| 4 | Rinkeby | +| 30 | Rootstock mainnet | +| 31 | Rootstock testnet | +| 42 | Kovan | +| 61 | Ethereum Classic mainnet | +| 62 | Ethereum Classic testnet | +| 1337 | Geth private chains (default) | diff --git a/EIPS/eip-158.md b/EIPS/eip-158.md new file mode 100644 index 00000000..46b945dc --- /dev/null +++ b/EIPS/eip-158.md @@ -0,0 +1,42 @@ +``` +EIP: 158 +Title: State clearing +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Superseded +Created: 2016-10-16 +Superseded-By: 161 +``` + +# Specification + +For all blocks where `block.number >= FORK_BLKNUM` (TBA): +1. In all cases where a state change is made to an account, and this state change results in the account state being saved with nonce = 0, balance = 0, code empty, storage empty (hereinafter "empty account"), the account is instead deleted. +2. If a address is "touched" and that address contains an empty account, then it is deleted. A "touch" is defined as any situation where if the account at the given address were nonexistent it would be created. +3. Whenever the EVM checks if an account exists, emptiness is treated as equivalent to nonexistence. Particularly, note that this implies that, once this change is enabled, there is no longer a meaningful difference between emptiness and nonexistence from the point of view of EVM execution. +4. Zero-value calls and zero-value suicides no longer consume the 25000 account creation gas cost in any circumstance + +The cases where a "touch" takes place can be enumerated as follows: +- Zero-value-bearing CALLs +- CREATEs (if the code that is ultimately saved is empty and there is no ether remaining in the account when it is saved) +- Zero-value-bearing SUICIDEs +- Transaction recipients +- Contracts created in contract creation transactions +- Miners receiving transaction fees (note the case where the gasprice is zero, and the account does not yet exist because it only receives the block/uncle/nephew rewards _after_ processing every transaction) +### Specification (1b) + +When the EVM checks for emptiness (for the purpose of possibly applying the 25000 gas cost), emptiness is defined by `is_empty(acct): return get_balance(acct) == 0 and get_code(acct) == "" and get_nonce(acct) == 0`; emptiness of storage does not matter. This simplifies client implementation because there is no need to add extra complexity to make caches enumerable in the correct way and does not significantly affect the intended result, as the cases where balance/code/nonce are empty but storage is nonempty where this change would lead to an extra 25000 gas being paid are pathological and have no real use value. +### Specification (1c) + +Do not implement point 2 above (ie. no new empty accounts can be created, but existing ones are not automatically destroyed unless their state is actually _changed_). Instead, during each block starting from (and including) N and ending when there are no null accounts left, select the 1000 null accounts that are left-most in order of sha3(address), and delete them (ordering by hash is necessary so as to allow the accounts to be easily found by iterating the tree). +# Rationale + +This removes a large number of empty accounts that have been put in the state at very low cost due to flaws in earlier versions of the Ethereum protocol, thereby greatly reducing state size and hence both reducing the hard disk load of a full client and reducing the time for a fast sync. Additionally, it simplifies the protocol in the long term, as once all "empty" objects are cleared out there is no longer any meaningful distinction between an account being empty and being nonexistent, and indeed one can simply view nonexistence as a compact representation of emptiness. + +Note that this proposal does introduce a **temporary** breaking of existing guarantees, in that by repeatedly zero-value-calling already existing empty accounts one can create a state change at a cost of 700 gas per account instead of the usual 5000 per gas minimum (with SUICIDE refunds this goes down further to 350 gas per account). Allowing such a large number of state writes per block will lead to heightened block processing times and increase uncle rates in the short term while the existing empty accounts are being cleared, and eventually once all empty accounts are cleared this issue will no longer exist. + +# References + +1. EIP-158 issue and discussion: https://github.com/ethereum/EIPs/issues/158 +2. EIP-161 issue and discussion: https://github.com/ethereum/EIPs/issues/161 diff --git a/EIPS/eip-160.md b/EIPS/eip-160.md new file mode 100644 index 00000000..c80d3841 --- /dev/null +++ b/EIPS/eip-160.md @@ -0,0 +1,21 @@ +``` +EIP: 160 +Title: EXP cost increase +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Final +Created: 2016-10-20 +``` + +### Specification + +If `block.number >= FORK_BLKNUM`, increase the gas cost of EXP from 10 + 10 per byte in the exponent to 10 + 50 per byte in the exponent. + +### Rationale + +Benchmarks suggest that EXP is currently underpriced by a factor of about 4-8. + +### References + +1. EIP-160 issue and discussion: https://github.com/ethereum/EIPs/issues/160 diff --git a/EIPS/eip-161.md b/EIPS/eip-161.md new file mode 100644 index 00000000..bd73c60a --- /dev/null +++ b/EIPS/eip-161.md @@ -0,0 +1,62 @@ +``` +EIP: 161 +Title: State trie clearing (invariant-preserving alternative) +Author: Gavin Wood +Type: Standard Track +Category: Core +Status: Final +Created: 2016-10-24 +``` + +# Specification + +a. Account creation transactions and the `CREATE` operation SHALL, prior to the execution of the initialisation code, **increment** the **nonce** over and above its normal starting value by **one** (for normal networks, this will be simply 1, however test-nets with non-zero default starting nonces will be different). + +b. Whereas `CALL` and `SUICIDE` would charge 25,000 gas when the destination is non-existent, now the charge SHALL **only** be levied if the operation transfers **more than zero value** and the destination account is _dead_. + +c. No account may _change state_ from non-existent to existent-but-_empty_. If an operation would do this, the account SHALL instead remain non-existent. + +d. _At the end of the transaction_, any account _touched_ by the execution of that transaction which is now _empty_ SHALL instead become non-existent (i.e. **deleted**). + +Where: + +An account is considered to be _touched_ when it is involved in any potentially _state-changing_ operation. This includes, but is not limited to, being the recipient of a **transfer of zero value**. + +An account is considered _empty_ when it has **no code** and **zero nonce** and **zero balance**. + +An account is considered _dead_ when either it is non-existent or it is _empty_. + +_At the end of the transaction_ is immediately following the execution of the suicide list, prior to the determination of the state trie root for receipt population. + +An account _changes state_ when: +- it is the target or refund of a `SUICIDE` operation for **zero or more** value; +- it is the source or destination of a `CALL` operation or message-call transaction transferring **zero or more** value; +- it is the source or newly-creation of a `CREATE` operation or contract-creation transaction endowing **zero or more** value; +- as the block author ("miner") it is recipient of block-rewards or transaction-fees of **zero or more**. + +## Notes + +In the present Ethereum protocol, it should be noted that very few state changes can ultimately result in accounts that are empty following the execution of the transaction. In fact there are only four contexts that current implementations need track: +- an empty account has zero value transferred to it through `CALL`; +- an empty account has zero value transferred to it through `SUICIDE`; +- an empty account has zero value transferred to it through a message-call transaction; +- an empty account has zero value transferred to it through a zero-gas-price fees transfer. + +# Rationale + +Same as #158 except that several edge cases are avoided since we do not break invariants: +- ~~that an account can go from having code and storage to not having code or storage mid-way through the execution of a transaction;~~ [corrected] +- that a newly created account cannot be deleted prior to being deployed. + +`CREATE` avoids zero in the nonce to avoid any suggestion of the oddity of `CREATE`d accounts being reaped half-way through their creation. + +# Addendum (2017-08-15) + +On 2016-11-24, a consensus bug occurred due to two implementations having different behavior in the case of state reverts.[3] The specification was amended to clarify that empty account deletions are reverted when the state is reverted. + +# References + +1. EIP-158 issue and discussion: https://github.com/ethereum/EIPs/issues/158 +2. EIP-161 issue and discussion: https://github.com/ethereum/EIPs/issues/161 +3. https://blog.ethereum.org/2016/11/25/security-alert-11242016-consensus-bug-geth-v1-4-19-v1-5-2/ +> Details: Geth was failing to revert empty account deletions when the transaction causing the deletions of empty accounts ended with an an out-of-gas exception. An additional issue was found in Parity, where the Parity client incorrectly failed to revert empty account deletions in a more limited set of contexts involving out-of-gas calls to precompiled contracts; the new Geth behavior matches Parity’s, and empty accounts will cease to be a source of concern in general in about one week once the state clearing process finishes. diff --git a/EIPS/eip-162.md b/EIPS/eip-162.md new file mode 100644 index 00000000..e0d46e95 --- /dev/null +++ b/EIPS/eip-162.md @@ -0,0 +1,244 @@ +``` +EIP: 162 +Title: Initial ENS Hash Registrar +Author: Maurelian and Nick Johnson +Status: Final +Type: Informational +Created: 2016-10-25 +``` + +## Contents +- Abstract +- Motivations +- Specification + - Initial restrictions + - Name format for hash registration + - Auctioning names + - Deeds + - Deployment and Upgrade process + - Registrar Interface +- Rationale + - Not committing to a permanent registrar at the outset + - Valid names >= 7 characters + - Restricting TLD to `.eth` + - Holding ether as collateral +- Prior work + + + +## Abstract + +This ERC describes the implementation, as deployed to the main ethereum network on 2017-05-04, of a registrar contract to govern the allocation of names in the Ethereum Name Service (ENS). The corresponding source code is [here](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol). + +For more background, refer to [EIP 137](https://github.com/ethereum/EIPs/issues/137). + +> Registrars are responsible for allocating domain names to users of the system, and are the only entities capable of updating the ENS; the owner of a node in the ENS registry is its registrar. Registrars may be contracts or externally owned accounts, though it is expected that the root and top-level registrars, at a minimum, will be implemented as contracts. +> +> \- EIP 137 + +A well designed and governed registrar is essential to the success of the ENS described in EIP 137, but is described separately in this document as it is external to the core ENS protocol. + +In order to maximize utility and adoption of a new namespace, the registrar should mitigate speculation and "name squatting", however the best approach for mitigation is unclear. Thus an "initial" registrar is proposed, which implements a simple approach to name allocation. During the initial period, the available namespace will be significantly restricted to the `.eth` top level domain, and subdomain shorter than 7 characters in length disallowed. This specification largely describes @alexvandesande and @arachnid's [hash registrar implementation](https://github.com/Arachnid/ens/blob/master/HashRegistrarSimplified.sol) in order to facilitate discussion. + +The intent is to replace the Initial Registrar contract with a permanent registrar contract. The Permanent Registrar will increase the available namespace, and incorporate lessons learned from the performance of the Initial Registrar. This upgrade is expected to take place within approximately 2 years of initial deployment. + +## Motivations + +The following factors should be considered in order to optimize for adoption of the ENS, and good governance of the Initial Registrar's namespace. + +**Upgradability:** The Initial Registrar should be safely upgradeable, so that knowledge gained during its deployment can be used to replace it with an improved and permanent registrar. + +**Effective allocation:** Newly released namespaces often create a land grab situation, resulting in many potentially valuable names being purchased but unused, with the hope of re-selling at a profit. This reduces the availability of the most useful names, in turn decreasing the utility of the name service to end users. + +Achieving an effective allocation may or may not require human intervention for dispute resolution and other forms of curation. The Initial Registrar should not aim to create to most effective possible allocation, but instead limit the cost of misallocation in the long term. + +**Security:** The registrar will hold a balance of ether without an explicit limit. It must be designed securely. + +**Simplicity:** The ENS specification itself emphasizes a separation of concerns, allowing the most essential element, the registry to be as simple as possible. The interim registrar in turn should be as simple as possible while still meeting its other design goals. + +**Adoption:** Successful standards become more successful due to network effects. The registrar should consider what strategies will encourage the adoption of the ENS in general, and the namespace it controls in particular. + +## Specification + +### Initial restrictions + +The Initial Registrar is expected to be in service for approximately two years, prior to upgrading. This should be sufficient time to learn, observe, and design an updated system. + +During the initial two year period, the available name space will be restricted to the `.eth` TLD. + +This restriction is enforced by the owner of the ENS root node who should not assign any nodes other than `.eth` to the Initial Registrar. The ENS's root node should be controlled by multiple parties using a multisig contract. + +The Initial Registrar will also prohibit registration of names 6 characters or less in length. + +### Name format for hash registration + +Names submitted to the initial registrar must be hashed using Ethereum's sha3 function. Note that the hashes submitted to the registrar are the hash of the subdomain label being registered, not the namehash as defined in EIP 137. + +For example, in order to register `abcdefg.eth`, one should submit `sha3('abcdefg')`, not `sha3(sha3(0, 'eth'), 'abcdefg')`. + +### Auctioning names + +The registrar will allocate the available names through a Vickrey auction: + +> A Vickrey auction is a type of sealed-bid auction. Bidders submit written bids without knowing the bid of the other people in the auction. The highest bidder wins but the price paid is the second-highest bid. This type of auction... gives bidders an incentive to bid their true value. +> +> \- [Vickrey Auction, Wikipedia](https://en.wikipedia.org/wiki/Vickrey_auction) + +The auction lifecycle of a name has 5 possible states, or Modes. + +1. **Not-yet-available:** The majority of names will be initially unavailable for auction, and will become available some time during the 8 weeks after launch. +2. **Open:** The earliest availability for a name is determined by the most significant byte of its sha3 hash. `0x00` would become available immediately, `0xFF` would become available after 8 weeks, and the availability of other names is distributed accordingly. Once a name is available, it is possible to start an auction on it. +3. **Auction:** Once the auction for a name has begun, there is a 72 hour bidding period. Bidders must submit a payment of ether, along with sealed bids as a hash of `sha3(bytes32 hash, address owner, uint value, bytes32 salt)`. The bidder may obfuscate the true bid value by sending a greater amount of ether. +4. **Reveal:** After the bidding period, a 48 hour reveal period commences. During this time, bidders must reveal the true parameters of their sealed bid. As bids are revealed, ether payments are returned according to the schedule of "refund ratios" outlined in the table below. If no bids are revealed, the name will return to the Open state. +5. **Owned:** After the reveal period has finished, the winning bidder must submit a transaction to finalize the auction, which then calls the ENS's `setSubnodeOwner` function, recording the winning bidder's address as the owner of the hash of the name. + +The following table outlines important parameters which define the Registrar's auction mechanism. + +#### Registrar Parameters + +| Name | Description | Value | +|--------------------|----------------------------------------------------------------------------------------------------|------------| +| totalAuctionLength | The full time period from start of auction to end of the reveal period. | 5 days | +| revealPeriod | The length of the time period during which bidding is no longer allowed, and bids must be revealed. | 48 hours | +| launchLength | The time period during which all names will become available for auction. | 8 weeks | +| minPrice | The minimum amount of ether which must be locked up in exchange for ownership of a name. | 0.01 ether | + +### Deeds + +The Initial Registrar contract does not hold a balance itself. All ether sent to the Registrar will be held in a separate `Deed` contracts. A deed contract is first created and funded when a sealed bid is submitted. After an auction is completed and a hash is registered, the deed for the winning bid is held in exchange for ownership of the hash. Non-winning bids are refunded. + +A deed for an owned name may be transferred to another account by its owner, thus transferring ownership and control of the name. + +After 1 year of registration, the owner of a hash may choose to relinquish ownership and have the value of the deed returned to them. + +Deeds for non-winning bids can be closed by various methods, at which time any ether held will either be returned to the bidder, burnt, or sent to someone else as a reward for actions which help the registrar. + +The following table outlines what portion of the balance held in a deed contract will be returned upon closure, and to whom. The remaining balance will be burnt. + +#### Refund schedule + +| Reason for Deed closure | Refund Recipient | Refund Percentage | +| --- | --- | --- | +| A valid non-winning bid is revealed. | Bidder | 99.5% | +| A bid submitted after the auction period is revealed. | Bidder | 99.5% | +| An otherwise valid bid is revealed on an owned name. 1 | Bidder | 0.5% | +| An expired sealed bid is cancelled. 2 | Canceler | 0.5% | +| A registered hash is reported as invalid. 3 | Reporter | 50% | +| A registered hash is reported as invalid. 3 | Owner | 50% | + +##### Notes: + +1. This incentivizes all bids to be revealed in time. If bids could be revealed late, an extortion attack on the current highest bidder could be made by threatening to reveal a new second highest bid. +2. A bid which remains sealed after more than 2 weeks and 5 days may be cancelled by anyone to collect a small reward. +2. Since names are hashed before auctioning and registration, the Initial Registrar is unable to enforce character length restrictions independently. A reward is therefore provided for reporting invalid names. + +### Deployment and Upgrade process + +The Initial Registrar requires the ENS's address as a contructor, and should be deployed after the ENS. The multisig account owning the root node in the ENS should then set the Initial Registrar's address as owner of the `eth` node. + +The Initial Registrar is expected to be replaced by a Permanent Registrar approximately 2 years after deployment. The following process should be used for the upgrade: +1. The Permanent Registrar contract will be deployed. +2. The multisig account owning the root node in the ENS will assign ownership of the `.eth` node to the Permanent Registrar. +3. Owners of hashes in the Initial Registrar will be responsible for registering their deeds to the Permanent Registrar. A couple options are considered here: + 1. Require owners to transfer their ownership prior to a cutoff date in order to maintain ownership and/or continue name resolution services. + 2. Have the Permanent Registrar query the Initial Registrar for ownership if it is lacking an entry. + +### Planned deactivation + +In order to limit dependence on the Initial Registrar, new auctions will stop after 4 years, and all ether held in deeds after 8 years will become unreachable. + +### Registrar Interface + +`function state(bytes32 _hash) constant returns (Mode)` +- Implements a state machine returning the current state of a name + +`function entries(bytes32 _hash) constant returns (Mode, address, uint, uint, uint)` +- Returns the following information regarding a registered name: + * state + * deed address + * registration date + * balance of the deed + * highest value bid at auction + +`function getAllowedTime(bytes32 _hash) constant returns (uint timestamp)` +- Returns the time at which the hash will no longer be in the initial `not-yet-available` state. + +`function isAllowed(bytes32 _hash, uint _timestamp) constant returns (bool allowed)` +- Takes a hash and a time, returns true if and only if it has passed the initial `not-yet-available` state. + +`function startAuction(bytes32 _hash);` +- Moves the state of a hash from Open to Auction. Throws if state is not Open. + +`function startAuctions(bytes32[] _hashes);` +- Starts multiple auctions on an array of hashes. This enables someone to open up an auction for a number of dummy hashes when they are only really interested in bidding for one. This will increase the cost for an attacker to simply bid blindly on all new auctions. Dummy auctions that are open but not bid on are closed after a week. + +`function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) constant returns (bytes32 sealedBid);` +- Takes the parameters of a bid, and returns the sealedBid hash value required to participate in the bidding for an auction. This obfuscates the parameters in order to mimic the mechanics of placing a bid in an envelope. + +`function newBid(bytes32 sealedBid);` +- Bids are sent by sending a message to the main contract with a sealedBid hash and an amount of ether. The hash contains information about the bid, including the bidded name hash, the bid value, and a random salt. Bids are not tied to any one auction until they are revealed. The value of the bid itself can be masqueraded by sending more than the value of your actual bid. This is followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable. Since this is an auction, it is expected that most public hashes, like known domains and common dictionary words, will have multiple bidders pushing the price up. + +`function startAuctionsAndBid(bytes32[] hashes, bytes32 sealedBid)` +- A utility function allowing a call to `startAuctions` followed by `newBid` in a single transaction. + + +`function unsealBid(bytes32 _hash, address _owner, uint _value, bytes32 _salt);` +- Once the bidding period is completed, there is a reveal period during with the properties of a bid are submitted to reveal them. The registrar hashes these properties using the `shaBid()` function above to verify that they match a pre-existing sealed bid. If the unsealedBid is the new best bid, the old best bid is returned to its bidder. + +`function cancelBid(bytes32 seal);` +- Cancels an unrevealed bid according to the rules described in the notes on the refund schedule above. + +`function finalizeAuction(bytes32 _hash);` + +After the registration date has passed, this function can be called to finalize the auction, which then calls the ENS function `setSubnodeOwner()` updating the ENS record to set the winning bidder as owner of the node. + +`function transfer(bytes32 _hash, address newOwner);` +- Update the owner of the ENS node corresponding to the submitted hash to a new owner. This function must be callable only by the current owner. + +`function releaseDeed(bytes32 _hash);` +- After some time, the owner can release the property and get their ether back. + +`function invalidateName(string unhashedName);` +- Since registration is done on the hash of a name, the registrar itself cannot validate names. This function can be used to report a name which is 6 characters long or less. If it has been registered, the submitter will earn 10% of the deed value. We are purposefully handicapping the simplified registrar as a way to force it into being restructured in a few years. + +`function eraseNode(bytes32[] labels)` +- Allows anyone to delete the owner and resolver records for a subdomain of a name that is not currently owned in the registrar. For instance, to zero `foo.bar.eth` on a registrar that owns `.eth`, pass an array containing `[sha3('foo'), sha3('bar')]`. + +`function transferRegistrars(bytes32 _hash) onlyOwner(_hash);` +- Used during the upgrade process to a permanent registrar. If this registrar is no longer the owner of the its root node in the ENS, this function will transfers the deed to the current owner, which should be a new registrar. This function throws if this registrar still owns its root node. + +## Rationale + +### Starting with a temporary registrar + +Anticipating and designing for all the potential issues of name allocation names is unlikely to succeed. This approach chooses not to be concerned with getting it perfect, but allows us to observe and learn with training wheels on, and implement improvements before expanding the available namespace to shorter names or another TLD. + +### Valid names >= 7 characters + +Preserving the shortest, and often most valuable, domain names for the upgraded registrar provides the opportunity to implement processes for dispute resolution (assuming they are found to be necessary). + +### Delayed release of names + +A slower release allows for extra time to identify, and address any issues which may arise after launch. + +### Restricting TLD to `.eth` + +Choosing a single TLD helps to maximize network effects by focusing on one namespace. + +A three letter TLD is a pattern made familiar by it's common usage in internet domain names. This familiarity significantly increases the potential of the ENS to be integrated into pre-existing DNS systems, and reserved as a [special-use domain name](http://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml#special-use-domain). A recent precedent for this is the [reservation of the `.onion` domain](https://tools.ietf.org/html/rfc7686). + +### Holding ether as collateral + +This approach is simpler than the familiar model of requiring owners to make recurring payments to retain ownership of a domain name. It also makes the initial registrar a revenue neutral service. + +## Prior work + +This document borrows heavily from several sources: +- [EIP 137](https://github.com/ethereum/EIPs/issues/137) outlines the initial implementation of the Registry Contract (ENS.sol) and associated Resolver contracts. +- [ERC 26](https://github.com/ethereum/EIPs/issues/26) was the first ERC to propose a name service at the contract layer +- @alexvandesande's current implementation of the [HashRegistrar](https://github.com/Arachnid/ens/blob/master/HashRegistrarSimplified.sol) + +### Edits: +- 2016-10-26 Added link Alex's design in abstract +- 2016-11-01 change 'Planned deactivation' to h3' +- 2017-03-13 Update timelines for bidding and reveal periods diff --git a/EIPS/eip-170.md b/EIPS/eip-170.md new file mode 100644 index 00000000..2dcd7a58 --- /dev/null +++ b/EIPS/eip-170.md @@ -0,0 +1,22 @@ +``` +EIP: 170 +Title: Contract code size limit +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Final +Created: 2016-11-04 +``` + +### Specification + +If `block.number >= FORK_BLKNUM`, then if contract creation initialization returns data with length of **more than** `0x6000` (`2**14 + 2**13`) bytes, contract creation fails with an out of gas error. + +### Rationale + +Currently, there remains one slight quadratic vulnerability in ethereum: when a contract is called, even though the call takes a constant amount of gas, the call can trigger O(n) cost in terms of reading the code from disk, preprocessing the code for VM execution, and also adding O(n) data to the Merkle proof for the block's proof-of-validity. At current gas levels, this is acceptable even if suboptimal. At the higher gas levels that could be triggered in the future, possibly very soon due to dynamic gas limit rules, this would become a greater concern - not nearly as serious as recent denial of service attacks, but still inconvenient especially for future light clients verifying proofs of validity or invalidity. The solution is to put a hard cap on the size of an object that can be saved to the blockchain, and do so non-disruptively by setting the cap at a value slightly higher than what is feasible with current gas limits. + +### References + +1. EIP-170 issue and discussion: https://github.com/ethereum/EIPs/issues/170 +2. pyethereum implementation: https://github.com/ethereum/pyethereum/blob/5217294871283d8dc4fb3ca9d8a78c7d416490e8/ethereum/messages.py#L397 diff --git a/EIPS/eip-181.md b/EIPS/eip-181.md new file mode 100644 index 00000000..bbd0f48e --- /dev/null +++ b/EIPS/eip-181.md @@ -0,0 +1,105 @@ +
+  EIP: 181
+  Title: ENS support for reverse resolution of Ethereum addresses
+  Author: Nick Johnson 
+  Status: Final
+  Type: Standard Track
+  Category: ERC
+  Created: 2016-12-01
+
+ +# Abstract +This EIP specifies a TLD, registrar, and resolver interface for reverse resolution of Ethereum addresses using ENS. This permits associating a human-readable name with any Ethereum blockchain address. Resolvers can be certain that the reverse record was published by the owner of the Ethereum address in question. + +# Motivation +While name services are mostly used for forward resolution - going from human-readable identifiers to machine-readable ones - there are many use-cases in which reverse resolution is useful as well: + + - Applications that allow users to monitor accounts benefit from showing the name of an account instead of its address, even if it was originally added by address. + - Attaching metadata such as descriptive information to an address allows retrieving this information regardless of how the address was originally discovered. + - Anyone can configure a name to resolve to an address, regardless of ownership of that address. Reverse records allow the owner of an address to claim a name as authoritative for that address. + +# Specification +Reverse ENS records are stored in the ENS hierarchy in the same fashion as regular records, under a reserved domain, `addr.reverse`. To generate the ENS name for a given account's reverse records, convert the account to hexadecimal representation in lower-case, and append `addr.reverse`. For instance, the ENS registry's address at `0x112234455c3a32fd11230c42e7bccd4a84e02010` has any reverse records stored at `112234455c3a32fd11230c42e7bccd4a84e02010.addr.reverse`. + +Note that this means that contracts wanting to do dynamic reverse resolution of addresses will need to perform hex encoding in the contract. + +## Registrar +The owner of the `addr.reverse` domain will be a registrar that permits the caller to take ownership of +the reverse record for their own address. It provides the following method: + + function claim(address owner) returns (bytes32 node); + +When called by account `x` it will instruct the ENS registry to transfer ownership of the name `hex(x) + '.addr.reverse'` to the provided address, and return the namehash of the ENS record thus transferred. + +Allowing the caller to specify an owner other than themselves for the relevant node facilitates contracts that need accurate reverse ENS entries delegating this to their creators with a minimum of code inside their constructor: + + reverseRegistrar.claim(msg.sender) + +## Resolver interface +A new resolver interface is defined, consisting of the following method: + + function name(bytes32 node) constant returns (string); + +Resolvers that implement this interface must return a valid ENS name for the requested node, or the empty string if no name is defined for the requested node. + +The interface ID of this interface is 0x691f3431. + +Future EIPs may specify more record types appropriate to reverse ENS records. + +# Appendix 1: Registrar implementation + +This registrar, written in Solidity, implements the specifications outlined above. + + pragma solidity ^0.4.0; + + import 'interface.sol'; + + contract ReverseRegistrar { + AbstractENS public ens; + bytes32 public rootNode; + + /** + * @dev Constructor + * @param ensAddr The address of the ENS registry. + * @param node The node hash that this registrar governs. + */ + function ReverseRegistrar(address ensAddr, bytes32 node) { + ens = AbstractENS(ensAddr); + rootNode = node; + } + + /** + * @dev Transfers ownership of the reverse ENS record associated with the + * calling account. + * @param owner The address to set as the owner of the reverse record in ENS. + * @return The ENS node hash of the reverse record. + */ + function claim(address owner) returns (bytes32 node) { + var label = sha3HexAddress(msg.sender); + ens.setSubnodeOwner(rootNode, label, owner); + return sha3(rootNode, label); + } + + /** + * @dev An optimised function to compute the sha3 of the lower-case + * hexadecimal representation of an Ethereum address. + * @param addr The address to hash + * @return The SHA3 hash of the lower-case hexadecimal encoding of the + * input address. + */ + function sha3HexAddress(address addr) constant returns (bytes32 ret) { + assembly { + let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000 + let i := 40 + loop: + i := sub(i, 1) + mstore8(i, byte(and(addr, 0xf), lookup)) + addr := div(addr, 0x10) + i := sub(i, 1) + mstore8(i, byte(and(addr, 0xf), lookup)) + addr := div(addr, 0x10) + jumpi(loop, i) + ret := sha3(0, 40) + } + } + } diff --git a/EIPS/eip-190.md b/EIPS/eip-190.md new file mode 100644 index 00000000..30e592a4 --- /dev/null +++ b/EIPS/eip-190.md @@ -0,0 +1,95 @@ +``` +EIP: 190 +Title: Ethereum Smart Contract Packaging Standard +Authors: Piper Merriam, Tim Coulter, Denis Erfurt (mhhf), RJ Catalano (VoR0220), Iuri Matias (iurimatias) +Status: Final +Type: Standards Track - ERC +Created: 2017-01-10 +``` + +# Abstract + +This ERC proposes a specification for Ethereum smart contract packages. + +The specification was collaboratively developed by the following Ethereum development framework maintainers. + +* Tim Coulter (Truffle) +* Denis Erfurt (Dapple) +* Piper Merriam (Populus) +* RJ Catalano (Eris PM) +* Iuri Matias (Embark) + +# Motivation + +Packaging is a core piece of modern software development which is missing from the Ethereum ecosystem. The lack of packaging limits the ability for developers to reuse code which negatively affects productivity and security. + +A key example of this is the ERC20 standard. There are a few well audited reusable token contracts available but most developers end up writing their own because of the difficulty in finding and reusing existing code. + +A packaging standard should have the following positive effects on the ecosystem: + +* Greater overall productivity caused by the ability to reuse existing code. +* Increased security caused by the ability to reuse existing well audited implementations of common patterns (ERC20, crowdfunding, etc). + +Smart contract packaging should also have a direct positive effect on the end user. Wallet software will be able to consume a released package and generate an interface for interacting with any deployed contracts included within that package. With the advent of [ENS](https://github.com/ethereum/EIPs/issues/137) all of the pieces will be in place for a wallet to take a human readable name and present the user with an interface for interacting with the underlying application. + + +# Specification + +The full specification for this standard is maintained separately in the repository [epm/epm-spec](https://github.com/ethpm/epm-spec). + +This EIP refers to the `1.0.0` version of the specification: [https://github.com/ethpm/epm-spec/tree/v1.0.0](https://github.com/ethpm/epm-spec/tree/v1.0.0) + +The specification contains details for a single document referred to as a *"Release Lockfile"*. + +* Release Lockfile Specification: [https://github.com/ethpm/epm-spec/blob/v1.0.0/release-lockfile.spec.md](https://github.com/ethpm/epm-spec/blob/v1.0.0/release-lockfile.spec.md). +* JSON Schema for Release Lockfile: [https://github.com/ethpm/epm-spec/blob/v1.0.0/spec/release-lockfile.spec.json](https://github.com/ethpm/epm-spec/blob/v1.0.0/spec/release-lockfile.spec.json) + +> These documents have not been inlined into this ERC to ensure that there is a single source of truth for the specification. + + +# Use Cases + +This specification covers the following types of smart contract packages. + +1. Packages with contracts intended to be used as base contract such as the common `owned` pattern. +2. Packages with contracts that are ready to use as-is such as an ERC20 token contract. +3. Packages with deployed contracts such as libraries or services. + +Full explanations and examples of these use cases can be found in the [`README.md`](https://github.com/ethpm/epm-spec/blob/v1.0.0/README.md#use-cases) from the `epm/epm-spec` repository. + + +# Package Managers + +The *Release Lockfile* is intended for consumption by package management software. Specific care was made to ensure that all of the following functionality can be implemented by package managers. + + +## Deterministic builds + +Ensures that a package will always resolve to the same set of dependencies and source files. Both source files and dependencies are content addressed to ensure that the referenced resources cannot change. + + +## Bytecode verification + +Contains the appropriate information for a package manager to inspect a deployed contract and verify that its bytecode matches the bytecode that results from compilation and linking of the package source code. + + +## Multi-chain deploys + +Supports deployments across multiple chains, allowing a package to define addresses on both the public mainnet and testnet. + + +## Trusted packages + +Allows for packages which exclude source code or other elements which would be needed for verification of the contract bytecode. This allows for minimalistic packages to be created for special situations where the package manager will not be performing verification. + + +# Framework support and integration + +Support for ERC190 is either implemented or in progress for the following: + +* [Truffle](http://truffleframework.com/) +* [Populus](http://populus.readthedocs.io/en/latest/) +* [Dapple](http://dapple.readthedocs.io/en/master/) +* [Eris PM](https://github.com/eris-ltd/eris-cli) +* [Embark](https://github.com/iurimatias/embark-framework) +* [Browser Solidity](https://github.com/ethereum/browser-solidity/issues/386) diff --git a/EIPS/eip-2.md b/EIPS/eip-2.md new file mode 100644 index 00000000..d31f61d2 --- /dev/null +++ b/EIPS/eip-2.md @@ -0,0 +1,51 @@ +``` +EIP: 2 +Title: Homestead Hard-fork Changes +Author: Vitalik Buterin +Status: Final +Type: Standard Track +Category: Core +Created: 2015-11-15 +``` + +# Specification + +If `block.number >= HOMESTEAD_FORK_BLKNUM` (e.g., 1.150.000 on livenet, 494.000 on Morden and 0 on future testnets), do the following: + +1. The gas cost *for creating contracts via a transaction* is increased from 21000 to 53000, ie. if you send a transaction and the to address is the empty string, the initial gas subtracted is 53000 plus the gas cost of the tx data, rather than 21000 as is currently the case. Contract creation from a contract using the `CREATE` opcode is unaffected. +2. All transaction signatures whose s-value is greater than `secp256k1n/2` are now considered invalid. The ECDSA recover precompiled contract remains unchanged and will keep accepting high s-values - this is useful if e.g. a contract recovers old Bitcoin signatures. +3. If contract creation does not have enough gas to pay for the final gas fee for adding the contract code to the state, the contract creation fails (ie. goes out-of-gas) rather than leaving an empty contract. +4. Change the difficulty adjustment algorithm from the current formula: `block_diff = parent_diff + parent_diff // 2048 * (1 if block_timestamp - parent_timestamp < 13 else -1) + int(2**((block.number // 100000) - 2))` (where the ` + int(2**((block.number // 100000) - 2))` represents the exponential difficulty adjustment component) to `block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2))`, where `//` is the integer division operator, eg. `6 // 2 = 3`, `7 // 2 = 3`, `8 // 2 = 4`. The `minDifficulty` still defines the minimum difficulty allowed and no adjustment may take it below this. + +# Rationale + +Currently, there is an excess incentive to create contracts via transactions, where the cost is 21000, rather than contracts, where the cost is 32000. Additionally, with the help of suicide refunds, it is currently possible to make a simple ether value transfer using only 11664 gas; the code for doing this is as follows: + +```python +from ethereum import tester as t +> from ethereum import utils +> s = t.state() +> c = s.abi_contract('def init():\n suicide(0x47e25df8822538a8596b28c637896b4d143c351e)', endowment=10**15) +> s.block.get_receipts()[-1].gas_used +11664 +> s.block.get_balance(utils.normalize_address(0x47e25df8822538a8596b28c637896b4d143c351e)) +1000000000000000 +``` +This is not a particularly serious problem, but is nevertheless arguably a bug. + +Allowing transactions with any s value with `0 < s < secp256k1n`, as is currently the case, opens a transaction malleability concern, as one can take any transaction, flip the s value from `s` to `secp256k1n - s`, flip the v value (`27 -> 28`, `28 -> 27`), and the resulting signature would still be valid. This is not a serious security flaw, especially since Ethereum uses addresses and not transaction hashes as the input to an ether value transfer or other transaction, but it nevertheless creates a UI inconvenience as an attacker can cause the transaction that gets confirmed in a block to have a different hash from the transaction that any user sends, interfering with user interfaces that use transaction hashes as tracking IDs. Preventing high s values removes this problem. + +Making contract creation go out-of-gas if there is not enough gas to pay for the final gas fee has the benefits that (i) it creates a more intuitive "success or fail" distinction in the result of a contract creation process, rather than the current "success, fail, or empty contract" trichotomy, (ii) makes failures more easily detectable, as unless contract creation fully succeeds then no contract account will be created at all, and (iii) makes contract creation safer in the case where there is an endowment, as there is a guarantee that either the entire initiation process happens or the transaction fails and the endowment is refunded. + +The difficulty adjustment change conclusively solves a problem that the Ethereum protocol saw two months ago where an excessive number of miners were mining blocks that contain a timestamp equal to `parent_timestamp + 1`; this skewed the block time distribution, and so the current block time algorithm, which targets a *median* of 13 seconds, continued to target the same median but the mean started increasing. If 51% of miners had started mining blocks in this way, the mean would have increased to infinity. The proposed new formula is roughly based on targeting the mean; one can prove that with the formula in use an average block time longer than 24 seconds is mathematically impossible in the long term. + +The use of `(block_timestamp - parent_timestamp) // 10` as the main input variable rather than the time difference directly serves to maintain the coarse-grained nature of the algorithm, preventing an excessive incentive to set the timestamp difference to exactly 1 in order to create a block that has slightly higher difficulty and that will thus be guaranteed to beat out any possible forks. The cap of -99 simply serves to ensure that the difficulty does not fall extremely far if two blocks happen to be very far apart in time due to a client security bug or other black-swan issue. + +# Implementation + +This is implemented in Python here: + +1. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L130 +2. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L129 +3. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L304 +4. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/blocks.py#L42 diff --git a/EIPS/eip-2.mediawiki b/EIPS/eip-2.mediawiki deleted file mode 100644 index 3ac2a3fc..00000000 --- a/EIPS/eip-2.mediawiki +++ /dev/null @@ -1,49 +0,0 @@ -
-  EIP: 2
-  Title: Homestead Hard-fork Changes
-  Author: Vitalik Buterin 
-  Status: Final
-  Type: Standard
-  Layer: Consensus (hard-fork)
-  Created: 2015-11-15
-
- -==Specification== - -If block.number >= HOMESTEAD_FORK_BLKNUM (e.g., 1.150.000 on livenet, 494.000 on Morden and 0 on future testnets), do the following: - -# The gas cost ''for creating contracts via a transaction'' is increased from 21000 to 53000, ie. if you send a transaction and the to address is the empty string, the initial gas subtracted is 53000 plus the gas cost of the tx data, rather than 21000 as is currently the case. Contract creation from a contract using the CREATE opcode is unaffected. -# All transaction signatures whose s-value is greater than secp256k1n/2 are now considered invalid. The ECDSA recover precompiled contract remains unchanged and will keep accepting high s-values - this is useful if e.g. a contract recovers old Bitcoin signatures. -# If contract creation does not have enough gas to pay for the final gas fee for adding the contract code to the state, the contract creation fails (ie. goes out-of-gas) rather than leaving an empty contract. -# Change the difficulty adjustment algorithm from the current formula: block_diff = parent_diff + parent_diff // 2048 * (1 if block_timestamp - parent_timestamp < 13 else -1) + int(2**((block.number // 100000) - 2)) (where the + int(2**((block.number // 100000) - 2)) represents the exponential difficulty adjustment component) to block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2)), where // is the integer division operator, eg. 6 // 2 = 3, 7 // 2 = 3, 8 // 2 = 4. The `minDifficulty` still defines the minimum difficulty allowed and no adjustment may take it below this. - -==Rationale== - -Currently, there is an excess incentive to create contracts via transactions, where the cost is 21000, rather than contracts, where the cost is 32000. Additionally, with the help of suicide refunds, it is currently possible to make a simple ether value transfer using only 11664 gas; the code for doing this is as follows: - -> from ethereum import tester as t -> from ethereum import utils -> s = t.state() -> c = s.abi_contract('def init():\n suicide(0x47e25df8822538a8596b28c637896b4d143c351e)', endowment=10**15) -> s.block.get_receipts()[-1].gas_used -11664 -> s.block.get_balance(utils.normalize_address(0x47e25df8822538a8596b28c637896b4d143c351e)) -1000000000000000 -This is not a particularly serious problem, but is nevertheless arguably a bug. - -Allowing transactions with any s value with 0 < s < secp256k1n, as is currently the case, opens a transaction malleability concern, as one can take any transaction, flip the s value from s to secp256k1n - s, flip the v value (27 -> 28, 28 -> 27), and the resulting signature would still be valid. This is not a serious security flaw, especially since Ethereum uses addresses and not transaction hashes as the input to an ether value transfer or other transaction, but it nevertheless creates a UI inconvenience as an attacker can cause the transaction that gets confirmed in a block to have a different hash from the transaction that any user sends, interfering with user interfaces that use transaction hashes as tracking IDs. Preventing high s values removes this problem. - -Making contract creation go out-of-gas if there is not enough gas to pay for the final gas fee has the benefits that (i) it creates a more intuitive "success or fail" distinction in the result of a contract creation process, rather than the current "success, fail, or empty contract" trichotomy, (ii) makes failures more easily detectable, as unless contract creation fully succeeds then no contract account will be created at all, and (iii) makes contract creation safer in the case where there is an endowment, as there is a guarantee that either the entire initiation process happens or the transaction fails and the endowment is refunded. - -The difficulty adjustment change conclusively solves a problem that the Ethereum protocol saw two months ago where an excessive number of miners were mining blocks that contain a timestamp equal to parent_timestamp + 1; this skewed the block time distribution, and so the current block time algorithm, which targets a ''median'' of 13 seconds, continued to target the same median but the mean started increasing. If 51% of miners had started mining blocks in this way, the mean would have increased to infinity. The proposed new formula is roughly based on targeting the mean; one can prove that with the formula in use an average block time longer than 24 seconds is mathematically impossible in the long term. - -The use of (block_timestamp - parent_timestamp) // 10 as the main input variable rather than the time difference directly serves to maintain the coarse-grained nature of the algorithm, preventing an excessive incentive to set the timestamp difference to exactly 1 in order to create a block that has slightly higher difficulty and that will thus be guaranteed to beat out any possible forks. The cap of -99 simply serves to ensure that the difficulty does not fall extremely far if two blocks happen to be very far apart in time due to a client security bug or other black-swan issue. - -==Implementation== - -This is implemented in Python here: - -# https://github.com/ethereum/pyethereum/blob/develop/ethereum/processblock.py#L130 -# https://github.com/ethereum/pyethereum/blob/develop/ethereum/processblock.py#L129 -# https://github.com/ethereum/pyethereum/blob/develop/ethereum/processblock.py#L304 -# https://github.com/ethereum/pyethereum/blob/develop/ethereum/blocks.py#L42 diff --git a/EIPS/eip-20-token-standard.md b/EIPS/eip-20-token-standard.md new file mode 100644 index 00000000..4b209dcd --- /dev/null +++ b/EIPS/eip-20-token-standard.md @@ -0,0 +1,184 @@ +## Preamble + + EIP: 20 + Title: ERC-20 Token Standard + Author: Fabian Vogelsteller , Vitalik Buterin + Type: Standard + Category: ERC + Status: Accepted + Created: 2015-11-19 + + +## Simple Summary + +A standard interface for tokens. + + +## Abstract + +The following standard allows for the implementation of a standard API for tokens within smart contracts. +This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party. + + +## Motivation + +A standard interface allows any tokens on Ethereum to be re-used by other applications: from wallets to decentralized exchanges. + + +## Specification + +## Token +### Methods + +**NOTE**: Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned! + + +#### name + +Returns the name of the token - e.g. `"MyToken"`. + +OPTIONAL - This method can be used to improve usability, +but interfaces and other contracts MUST NOT expect these values to be present. + + +``` js +function name() constant returns (string name) +``` + + +#### symbol + +Returns the symbol of the token. E.g. "HIX". + +OPTIONAL - This method can be used to improve usability, +but interfaces and other contracts MUST NOT expect these values to be present. + +``` js +function symbol() constant returns (string symbol) +``` + + + +#### decimals + +Returns the number of decimals the token uses - e.g. `8`, means to divide the token amount by `100000000` to get its user representation. + +OPTIONAL - This method can be used to improve usability, +but interfaces and other contracts MUST NOT expect these values to be present. + +``` js +function decimals() constant returns (uint8 decimals) +``` + + +#### totalSupply + +Returns the total token supply. + +``` js +function totalSupply() constant returns (uint256 totalSupply) +``` + + + +#### balanceOf + +Returns the account balance of another account with address `_owner`. + +``` js +function balanceOf(address _owner) constant returns (uint256 balance) +``` + + + +#### transfer + +Transfers `_value` amount of tokens to address `_to`, and MUST fire the `Transfer` event. +The function SHOULD `throw` if the `_from` account balance does not have enough tokens to spend. + +A token contract which creates new tokens SHOULD trigger a Transfer event with the `_from` address set to `0x0` when tokens are created. + +*Note* Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event. + +``` js +function transfer(address _to, uint256 _value) returns (bool success) +``` + + + +#### transferFrom + +Transfers `_value` amount of tokens from address `_from` to address `_to`, and MUST fire the `Transfer` event. + +The `transferFrom` method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. +This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. +The function SHOULD `throw` unless the `_from` account has deliberately authorized the sender of the message via some mechanism. + +*Note* Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event. + +``` js +function transferFrom(address _from, address _to, uint256 _value) returns (bool success) +``` + + + +#### approve + +Allows `_spender` to withdraw from your account multiple times, up to the `_value` amount. If this function is called again it overwrites the current allowance with `_value`. + +**NOTE**: To prevent attack vectors like the one [described here](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/) and discussed [here](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729), +clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to `0` before setting it to another value for the same spender. +THOUGH The contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before + +``` js +function approve(address _spender, uint256 _value) returns (bool success) +``` + + +#### allowance + +Returns the amount which `_spender` is still allowed to withdraw from `_owner`. + +``` js +function allowance(address _owner, address _spender) constant returns (uint256 remaining) +``` + + + +### Events + + +#### Transfer + +MUST trigger when tokens are transferred, including zero value transfers. + +``` js +event Transfer(address indexed _from, address indexed _to, uint256 _value) +``` + + + +#### Approval + +MUST trigger on any successful call to `approve(address _spender, uint256 _value)`. + +``` js +event Approval(address indexed _owner, address indexed _spender, uint256 _value) +``` + + + +## Implementation + +There are already plenty of ERC20-compliant tokens deployed on the Ethereum network. +Different implementations have been written by various teams that have different trade-offs: from gas saving to improved security. + +#### Example implementations are available at +- https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/StandardToken.sol +- https://github.com/ConsenSys/Tokens/blob/master/contracts/StandardToken.sol + +#### Implementation of adding the force to 0 before calling "approve" again: +- https://github.com/Giveth/minime/blob/master/contracts/MiniMeToken.sol + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-213.md b/EIPS/eip-213.md new file mode 100644 index 00000000..4b651fd1 --- /dev/null +++ b/EIPS/eip-213.md @@ -0,0 +1,106 @@ +## Preamble + + EIP: 213 + Title: Precompiled contracts for addition and scalar multiplication + on the elliptic curve alt_bn128 + Author: Christian Reitwiessner + Type: Standard Track + Category: Core + Status: Final + Created: 2017-02-02 + +## Simple Summary + +Precompiled contracts for elliptic curve operations are required in order to perform zkSNARK verification within the block gas limit. + +## Abstract + +This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-212](./eip-212.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property). + +## Motivation + +Current smart contract executions on Ethereum are fully transparent, which makes them unsuitable for several use-cases that involve private information like the location, identity or history of past transactions. The technology of zkSNARKs could be a solution to this problem. While the Ethereum Virtual Machine can make use of zkSNARKs in theory, they are currently too expensive +to fit the block gas limit. Because of that, this EIP proposes to specify certain parameters for some elementary primitives that enable zkSNARKs so that they can be implemented more efficiently and the gas cost be reduced. + +Note that while fixing these parameters might look like limiting the use-cases for zkSNARKs, the primitives are so basic that they can be combined in ways that are flexible enough so that it should even be possible to allow future advances in zkSNARK research without the need for a further hard fork. + +## Specification + +If `block.number >= BYZANTIUM_FORK_BLKNUM`, add precompiled contracts for point addition (ADD) and scalar multiplication (MUL) on the elliptic curve "alt_bn128". + +Address of ADD: 0x6 +Address for MUL: 0x7 + +The curve is defined by: +``` +Y^2 = X^3 + 3 +over the field F_p with +p = 21888242871839275222246405745257275088696311157297823662689037894645226208583 +``` + +### Encoding + +Field elements and scalars are encoded as 32 byte big-endian numbers. Curve points are encoded as two field elements `(x, y)`, where the point at infinity is encoded as `(0, 0)`. + +Tuples of objects are encoded as their concatenation. + +For both precompiled contracts, if the input is shorter than expected, it is assumed to be virtually padded with zeros at the end (i.e. compatible with the semantics of the `CALLDATALOAD` opcode). If the input is longer than expected, surplus bytes at the end are ignored. + +The length of the returned data is always as specified (i.e. it is not "unpadded"). + +### Exact semantics + +Invalid input: For both contracts, if any input point does not lie on the curve or any of the field elements (point coordinates) is equal or larger than the field modulus p, the contract fails. The scalar can be any number between `0` and `2**256-1`. + +#### ADD +Input: two curve points `(x, y)`. +Output: curve point `x + y`, where `+` is point addition on the elliptic curve `alt_bn128` specified above. +Fails on invalid input and consumes all gas provided. + +#### MUL +Input: curve point and scalar `(x, s)`. +Output: curve point `s * x`, where `*` is the scalar multiplication on the elliptic curve `alt_bn128` specified above. +Fails on invalid input and consumes all gas. + +### Gas costs + + - Gas cost for ``ECADD``: 500 + - Gas cost for ``ECMUL``: 40000 + +## Rationale + +The specific curve `alt_bn128` was chosen because it is particularly well-suited for zkSNARKs, or, more specifically their verification building block of pairing functions. Furthermore, by choosing this curve, we can use synergy effects with ZCash and re-use some of their components and artifacts. + +The feature of adding curve and field parameters to the inputs was considered but ultimately rejected since it complicates the specification: The gas costs are much harder to determine and it would be possible to call the contracts on something which is not an actual elliptic curve. + +A non-compact point encoding was chosen since it still allows to perform some operations in the smart contract itself (inclusion of the full y coordinate) and two encoded points can be compared for equality (no third projective coordinate). + +## Backwards Compatibility + +As with the introduction of any precompiled contract, contracts that already use the given addresses will change their semantics. Because of that, the addresses are taken from the "reserved range" below 256. + +## Test Cases + +Inputs to test: + + - Curve points which would be valid if the numbers were taken mod p (should fail). + - Both contracts should succeed on empty input. + - Truncated input that results in a valid curve point. + - Points not on curve (but valid otherwise). + - Multiply point with scalar that lies between the order of the group and the field (should succeed). + - Multiply point with scalar that is larger than the field order (should succeed). + +## Implementation + +Implementation of these primitives are available here: + + - [libff](https://github.com/scipr-lab/libff/blob/master/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp) (C++) + - [bn](https://github.com/zcash/bn/blob/master/src/groups/mod.rs) (Rust) + +In both codebases, a specific group on the curve alt_bn128 is used and is called G1. + + - [Python](https://github.com/ethereum/py_pairing/blob/master/py_ecc/bn128/bn128_curve.py) - probably most self-contained and best readable. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-5.md b/EIPS/eip-5.md index 243d77ca..02408e2f 100644 --- a/EIPS/eip-5.md +++ b/EIPS/eip-5.md @@ -21,10 +21,10 @@ the time the `CALL` returns. ### Specification -The gas and memory semantics for `CALL` and `CALLCODE` (and `DELEGATE_CALL`, if adopted, see EIP-4) +The gas and memory semantics for `CALL`, `CALLCODE` and `DELEGATECALL` (called later as `CALL*`) are changed in the following way (`CREATE` does not write to memory and is thus unaffected): -Suppose the arguments to `CALL` / `CALLCODE` are `gas, address, value, input_start, input_size, output_start, output_size)`, +Suppose the arguments to `CALL*` are `gas, address, value, input_start, input_size, output_start, output_size`, then, at the beginning of the opcode, gas for growing memory is only charged for `input_start + input_size`, but not for `output_start + output_size`. diff --git a/EIPS/eip-55.md b/EIPS/eip-55.md new file mode 100644 index 00000000..d7f0369c --- /dev/null +++ b/EIPS/eip-55.md @@ -0,0 +1,109 @@ +``` +EIP: 55 +Title: Mixed-case checksum address encoding +Author: Vitalik Buterin +Type: Standard Track +Category: ERC +Status: Accepted +Created: 2016-01-14 +``` + +# Specification + +Code: + +``` python +from ethereum import utils + +def checksum_encode(addr): # Takes a 20-byte binary address as input + o = '' + v = utils.big_endian_to_int(utils.sha3(addr.hex())) + for i, c in enumerate(addr.hex()): + if c in '0123456789': + o += c + else: + o += c.upper() if (v & (2**(255 - 4*i))) else c.lower() + return '0x'+o + +def test(addrstr): + assert(addrstr == checksum_encode2(bytes.fromhex(addrstr[2:]))) + +test('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed') +test('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359') +test('0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB') +test('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb') + +``` + +In English, convert the address to hex, but if the `i`th digit is a letter (ie. it's one of `abcdef`) print it in uppercase if the `4*i`th bit of the hash of the lowercase hexadecimal address is 1 otherwise print it in lowercase. + +# Implementation + +In javascript: + +```js +const createKeccakHash = require('keccak') + +function toChecksumAddress (address) { + address = address.toLowerCase().replace('0x',''); + var hash = createKeccakHash('keccak256').update(address).digest('hex') + var ret = '0x' + + for (var i = 0; i < address.length; i++) { + if (parseInt(hash[i], 16) >= 8) { + ret += address[i].toUpperCase() + } else { + ret += address[i] + } + } + + return ret +} +``` + +``` +> toChecksumAddress('0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359') +'0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359' +``` + +Note that the input to the Keccak256 hash is the lowercase hexadecimal string (i.e. the hex address encoded as ASCII): + +``` + var hash = createKeccakHash('keccak256').update(Buffer.from(address.toLowerCase(), 'ascii')).digest() +``` + +# Rationale + +Benefits: +- Backwards compatible with many hex parsers that accept mixed case, allowing it to be easily introduced over time +- Keeps the length at 40 characters +- On average there will be 15 check bits per address, and the net probability that a randomly generated address if mistyped will accidentally pass a check is 0.0247%. This is a ~50x improvement over ICAP, but not as good as a 4-byte check code. + +# Adoption + +| Wallet | displays checksummed addresses | rejects invalid mixed-case | rejects too short | rejects too long | +|--------------------------|--------------------------------|----------------------------|-------------------|------------------| +| Etherwall 2.0.1 | Yes | Yes | Yes | Yes | +| Jaxx 1.2.17 | No | Yes | Yes | Yes | +| MetaMask 3.7.8 | Yes | Yes | Yes | Yes | +| Mist 0.8.10 | Yes | Yes | Yes | Yes | +| MyEtherWallet v3.9.4 | Yes | Yes | Yes | Yes | +| Parity 1.6.6-beta (UI) | Yes | Yes | Yes | Yes | + +### Exchange support for mixed-case address checksums, as of 2017-05-27: + +| Exchange | displays checksummed deposit addresses | rejects invalid mixed-case | rejects too short | rejects too long | +|--------------|----------------------------------------|----------------------------|-------------------|------------------| +| Bitfinex | No | Yes | Yes | Yes | +| Coinbase | Yes | No | Yes | Yes | +| GDAX | Yes | Yes | Yes | Yes | +| Kraken | No | No | Yes | Yes | +| Poloniex | No | No | Yes | Yes | +| Shapeshift | No | No | Yes | Yes | + +# References + +1. EIP 55 issue and discussion https://github.com/ethereum/eips/issues/55 +2. Python example by @Recmo https://github.com/ethereum/eips/issues/55#issuecomment-261521584 +3. Python implementation in [`ethereum-utils`](https://github.com/pipermerriam/ethereum-utils#to_checksum_addressvalue---text) +4. Ethereumjs-util implementation https://github.com/ethereumjs/ethereumjs-util/blob/75f529458bc7dc84f85fd0446d0fac92d991c262/index.js#L452-L466 diff --git a/EIPS/eip-6.md b/EIPS/eip-6.md index 000bd4b1..d6d2bc8f 100644 --- a/EIPS/eip-6.md +++ b/EIPS/eip-6.md @@ -3,7 +3,7 @@ EIP: 6 Title: Renaming SUICIDE opcode Author: Hudson Jameson - Status: Draft + Status: Final Type: Standards Track Layer: Applications Created: 2015-11-22 diff --git a/EIPS/eip-606.md b/EIPS/eip-606.md new file mode 100644 index 00000000..b2ecb847 --- /dev/null +++ b/EIPS/eip-606.md @@ -0,0 +1,32 @@ +## Preamble + + EIP: 606 + Title: Hardfork Meta: Homestead + Author: Alex Beregszaszi + Type: Meta + Status: Final + Created: 2017-04-23 + Requires: 2, 7 + +## Abstract + +This specifies the changes included in the hard fork named Homestead. + +## Specification + +- Codename: Homestead +- Activation: + - Block >= 1,150,000 on Mainnet + - Block >= 494,000 on Morden + - Block >= 0 on future testnets +- Included EIPs: + - [EIP 2](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md) (Homestead Hard-fork Changes) + - [EIP 7](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7.md) (DELEGATECALL) + +## References + +1. https://blog.ethereum.org/2016/02/29/homestead-release/ + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-607.md b/EIPS/eip-607.md new file mode 100644 index 00000000..15a2a2f2 --- /dev/null +++ b/EIPS/eip-607.md @@ -0,0 +1,35 @@ + +## Preamble + + EIP: 607 + Title: Hardfork Meta: Spurious Dragon + Author: Alex Beregszaszi + Type: Meta + Status: Final + Created: 2017-04-23 + Requires: 155, 160, 161, 170 + +## Abstract + +This specifies the changes included in the hard fork named Spurious Dragon. + +## Specification + +- Codename: Spurious Dragon +- Aliases: State-clearing +- Activation: + - Block >= 2,675,000 on Mainnet + - Block >= 1,885,000 on Morden +- Included EIPs: + - [EIP 155](eip-155.md) (Simple replay attack protection) + - [EIP 160](eip-160.md) (EXP cost increase) + - [EIP 161](eip-161.md) (State trie clearing) + - [EIP 170](eip-170.md) (Contract code size limit) + +## References + +1. https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon/ + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-608.md b/EIPS/eip-608.md new file mode 100644 index 00000000..22ee846e --- /dev/null +++ b/EIPS/eip-608.md @@ -0,0 +1,31 @@ +## Preamble + + EIP: 608 + Title: Hardfork Meta: Tangerine Whistle + Author: Alex Beregszaszi + Type: Meta + Status: Final + Created: 2017-04-23 + Requires: 150 + +## Abstract + +This specifies the changes included in the hard fork named Tangerine Whistle (EIP 150). + +## Specification + +- Codename: Tangerine Whistle +- Aliases: EIP 150, Anti-DoS +- Activation: + - Block >= 2,463,000 on Mainnet +- Included EIPs: + - [EIP 150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) (Gas cost changes for IO-heavy operations) + +## References + +1. https://blog.ethereum.org/2016/10/13/announcement-imminent-hard-fork-eip150-gas-cost-changes/ +2. https://blog.ethereum.org/2016/10/18/faq-upcoming-ethereum-hard-fork/ + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-609.md b/EIPS/eip-609.md new file mode 100644 index 00000000..4ac78781 --- /dev/null +++ b/EIPS/eip-609.md @@ -0,0 +1,40 @@ +## Preamble + + EIP: 609 + Title: Hardfork Meta: Byzantium + Author: Alex Beregszaszi + Type: Standard Track + Category: Core + Status: Draft + Created: 2017-04-23 + Requires: 100, 140, 196, 197, 198, 211, 214, 649, 658 + +## Abstract + +This specifies the changes included in the hard fork named Byzantium. + +## Specification + +- Codename: Byzantium +- Aliases: Metropolis/Byzantium, Metropolis part 1 +- Activation: + - Block >= 4,370,000 on Mainnet + - Block >= 1,700,000 on Ropsten testnet +- Included EIPs: + - EIP 100 (Change difficulty adjustment to target mean block time including uncles) + - EIP 140 (REVERT instruction in the Ethereum Virtual Machine) + - EIP 196 (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128) + - EIP 197 (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128) + - EIP 198 (Precompiled contract for bigint modular exponentiation) + - EIP 211 (New opcodes: RETURNDATASIZE and RETURNDATACOPY) + - EIP 214 (New opcode STATICCALL) + - EIP 649 (Difficulty Bomb Delay and Block Reward Reduction) + - EIP 658 (Embedding transaction return data in receipts) + +## References + +1. https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/ + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-615.md b/EIPS/eip-615.md new file mode 100644 index 00000000..b78f1391 --- /dev/null +++ b/EIPS/eip-615.md @@ -0,0 +1,372 @@ +``` +EIP: 615 +Title: Subroutines and Static Jumps for the EVM +Status: Draft +Type: Core +Author: Greg Colvin , Paweł Bylica, Christian Reitwiessner +Created: 2016-12-10 +Edited: 2017-25-4 +``` +## Abstract + +This EIP introduces new EVM opcodes and conditions on EVM code to support subroutines and static jumps, disallow dynamic jumps, and thereby make EVM code amenable to linear-time static analysis. This will provide for better compilation, interpretation, transpilation, and formal analysis of EVM code. + +## MOTIVATION + +All current implementations of the Ethereum Virtual Machine, including the just-in-time compilers, are much too slow. This proposal identifies a major reason for this and proposes changes to the EVM specification to address the problem. + +In particular, it imposes restrictions on current EVM code and proposes new instructions to help provide for +* better-optimized compilation to native code +* faster interpretation +* faster transpilation to eWASM +* better compilation from other languages, + including eWASM and Solidity +* better formal analysis tools + +These goals are achieved by +* disallowing dynamic jumps +* introducing subroutines - jumps with return support +* disallowing pathological control flow and uses of the stack + +We also propose to validate - in linear time - that EVM contracts correctly use subroutines, avoid misuse of the stack, and meet other safety conditions _before_ placing them on the blockchain. Validated code precludes most runtime exceptions and the need to test for them. And well-behaved control flow and use of the stack makes life easier for interpreters, compilers, formal analysis, and other tools. + +## THE PROBLEM + +Currently the EVM supports dynamic jumps, where the address to jump to is an argument on the stack. These dynamic jumps obscure the structure of the code and thus mostly inhibit control- and data-flow analysis. This puts the quality and speed of optimized compilation fundamentally at odds. Further, since every jump can potentially be to any jump destination in the code, the number of possible paths through the code goes up as the product of the number of jumps by the number of destinations, as does the time complexity of static analysis. But absent dynamic jumps code can be statically analyzed in linear time. + +Static analysis includes validation, and much of optimization, compilation, transpilation, and formal analysis; every part of the tool chain benefits when linear-time analysis is available. In particular, faster control-flow analysis means faster compilation of EVM code to native code, and better data-flow analysis can help the compiler and the interpreter better track the size of the values on the stack and use native 64- and 32-bit operations when possible. Also, conditions which are checked at validation time don’t have to be checked repeatedly at runtime. + +Note that analyses of a contract’s bytecode before execution - such as optimizations performed before interpretation, JIT compilation, and on-the-fly machine code generation - must be efficient and linear-time. Otherwise, specially crafted contracts can be used as attack vectors against clients that use static analysis of EVM code before the creation or execution of contracts. + +## PROPOSAL + +We propose to deprecate two existing instructions - `JUMP` and `JUMPI`. They take their argument on the stack, which means that unless the value is constant they can jump to any `JUMPDEST`. (In simple cases like `PUSH 0 JUMP` the value on the stack can be known to be constant, but in general it's difficult.) We must nonetheless continue to support them in old code. + +Having deprecated `JUMP` and `JUMPI`, we propose new instructions to support their legitimate uses. + +### Preliminaries + +These forms +* `INSTRUCTION x,` +* `INSTRUCTION x, y` +* `INSTRUCTION n, x ...` + +name instructions with one, two, and two or more arguments, respectively. An instruction is represented in the bytecode as a single-byte opcode. The arguments are laid out as immediate data bytes following the opcode. The size and encoding of immediate data fields is open to change. In particular, easily-parsed variable-length encodings might prove useful for bytecode offsets - which are in practice small but in principle can be large. + +### Primitives + +The two most important uses of `JUMP` and `JUMPI` are static jumps and return jumps. Conditional and unconditional static jumps are the mainstay of control flow. Return jumps are implemented as a dynamic jump to a return address pushed on the stack. With the combination of a static jump and a dynamic return jump you can - and Solidity does - implement subroutines. The problem is that static analysis cannot tell the one place the return jump is going, so it must analyze every possibility. + +Static jumps are provided by +* `JUMPTO jump_target` +* `JUMPIF jump_target` +which are the same as `JUMP` and `JUMPI` except that they jump to an immediate `jump_target`, given as four immediate bytes, rather than an address on the stack. + +To support subroutines, `BEGINSUB`, `JUMPSUB`, and `RETURNSUB` are provided. Brief descriptions follow, and full semantics are given below. + +* `BEGINSUB n_args, n_results` +marks the **single** entry to a subroutine. `n_args` items are taken off of the stack at entry to, and `n_results` items are placed on the stack at return from the subroutine. `n_args` and `n_results` are given as one immediate byte each. The bytecode for a subroutine ends at the next `BEGINSUB` instruction (or `BEGINDATA`, below) or at the end of the bytecode. + +* `JUMPSUB jump_target` +jumps to an immediate subroutine address, given as four immediate bytes. + +* `RETURNSUB` +returns from the current subroutine to the instruction following the JUMPSUB that entered it. + +These five simple instructions form the primitives of the proposal. + +### Data + +In order to validate subroutines, EVM bytecode must be sequentially scanned matching jumps to their destinations. Since creation code has to contain the runtime code as data, that code might not correctly validate in the creation context and also does not have to be validated prior to the execution of the creation code. Because of that, there needs to be a way to place data into the bytecode that will be skipped over and not validated. Such data will prove useful for other purposes as well. + +* `BEGINDATA` +specifies that all of the following bytes to the end of the bytecode are data, and not reachable code. + +### Indirect Jumps + +The primitive operations provide for static jumps. Dynamic jumps are also used for O(1) indirection: an address to jump to is selected to push on the stack and be jumped to. So we also propose two more instructions to provide for constrained indirection. We support these with vectors of `JUMPDEST` or `BEGINSUB` offsets stored inline, which can be selected with an index on the stack. That constrains validation to a specified subset of all possible destinations. The danger of quadratic blow up is avoided because it takes as much space to store the jump vectors as it does to code the worst case exploit. + +Dynamic jumps to a `JUMPDEST` are used to implement O(1) jumptables, which are useful for dense switch statements, and are implemented as instructions similar to this one on most CPUs. +* `JUMPV n, jumpdest ...` +jumps to one of a vector of `n` `JUMPDEST` offsets via a zero-based index on the stack. The vector is stored inline in the bytecode. If the index is greater than or equal to `n - 1` the last (default) offset is used. `n` is given as four immediate bytes, all `JUMPDEST` offsets as four immediate bytes each. + +Dynamic jumps to a `BEGINSUB` are used to implement O(1) virtual functions and callbacks, which take just two pointer dereferences on most CPUs. +* `JUMPSUBV n, beginsub ...` +jumps to one of a vector of `n` `BEGINSUB` offsets via a zero-based index on the stack. The vector is stored inline in the bytecode, MSB-first. If the index is greater than or equal to `n - 1` the last (default) offset is used. `n` is given as four immediate bytes, the `n` offsets as four immediate bytes each. + +`JUMPV` and `JUMPSUBV` are not strictly necessary. They provide O(1) operations that can be replaced by O(n) or O(log n) EVM code using static jumps, but that code will be slower, larger and use more gas for things that can and should be fast, small, and cheap, and that are directly supported in WASM with br_table and call_indirect. + +### Variable Access + +These operations provide convenient access to subroutine parameters and other variables at fixed stack offsets within a subroutine. + +* `PUTLOCAL n` +Pops the top value on the stack and copies it to local variable `n`. + +* `GETLOCAL n` +Pushes the value of local variable `n` on the EVM stack. + +Local variable `n` is `FP[-n]` as defined below. + +## SEMANTICS + +Jumps to and returns from subroutines are described here in terms of +* the EVM data stack, (as defined in the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) usually just called “the stack”, +* a return stack of `JUMPSUB` and `JUMPSUBV` offsets, and +* a frame stack of frame pointers. + +We will adopt the following conventions to describe the machine state: +* The _program counter_ `PC` is (as usual) the byte offset of the currently executing instruction. +* The _stack pointer_ `SP` corresponds to the number of items on the stack - the _stack size_. As a negative offset it addresses the current top of the stack of data values, where new items are pushed. +* The _frame pointer_ `FP` is set to `SP + n_args` at entry to the currently executing subroutine. +* The _stack items_ between the frame pointer and the current stack pointer are called the _frame_. +* The current number of items in the frame, `FP - SP`, is the _frame size_. + +Defining the frame pointer so as to include the arguments is unconventional, but better fits our stack semantics and simplifies the remainder of the proposal. + +The frame pointer and return stacks are internal to the subroutine mechanism, and not directly accessible to the program. This is necessary to prevent the program from modifying its state in ways that could be invalid. + +The first instruction of an array of EVM bytecode begins execution of a _main_ routine with no arguments, `SP` and `FP` set to 0, and with one value on the return stack - `code size - 1`. (Executing the virtual byte of 0 after this offset causes an EVM to stop. Thus executing a `RETURNSUB` with no prior `JUMPSUB` or `JUMBSUBV` - that is, in the _main_ routine - executes a `STOP`.) + +Execution of a subroutine begins with `JUMPSUB` or `JUMPSUBV`, which +* push `PC` on the return stack, +* push `FP` on the frame stack, +thus suspending execution of the current subroutine, and +* set `FP` to `SP + n_args`, and +* set `PC` to the specified `BEGINSUB` address, +thus beginning execution of the new subroutine. +(The _main_ routine is not addressable by `JUMPSUB` instructions.) + +Execution of a subroutine is suspended during and resumed after execution of nested subroutines, and ends upon encountering a `RETURNSUB`, which +* sets `FP` to the top of the virtual frame stack and pops the stack, and +* sets `PC` to top of the return stack and pops the stack +* advances `PC` to the next instruction +thus resuming execution of the enclosing subroutine or _main_ program. +A `STOP or `RETURN` also ends the execution of a subroutine. + +## VALIDITY + +We would like to consider EVM code valid if and only if no execution of the program can lead to an exceptional halting state. But we must and will validate code in linear time. So our validation does not consider the code’s data and computations, only its control flow and stack use. This means we will reject programs with invalid code paths, even if those paths cannot be executed at runtime. Most conditions can be validated, and will not need to be checked at runtime; the exceptions are sufficient gas and sufficient stack. So some false negatives and runtime checks are the price we pay for linear time validation. + +_Execution_ is as defined in the Yellow Paper - a sequence of changes in the EVM state. The conditions on valid code are preserved by state changes. At runtime, if execution of an instruction would violate a condition the execution is in an exceptional halting state. The yellow paper defines five such states. +>1 Insufficient gas + +>2 More than 1024 stack items + +>3 Insufficient stack items + +>4 Invalid jump destination + +>5 Invalid instruction + +We propose to expand and extend the Yellow Paper conditions to handle the new instructions we propose. + +To handle the return stack we expand the conditions on stack size: +>2a The size of the data stack does not exceed 1024. + +>2b The size of the return stack does not exceed 1024. + +Given our more detailed description of the data stack we restate condition 3 - stack underflow - as +>3 `SP` must be less than or equal to `FP` + +Since the various `DUP` and `SWAP` operations are formalized as taking items off the stack and putting them back on, this prevents `DUP` and `SWAP` from accessing data below the frame pointer, since taking too many items off of the stack would mean that `SP` is less than `FP`. + +To handle the new jump instructions and subroutine boundaries we expand the conditions on jumps and jump destinations. +>4a `JUMPTO`, `JUMPIF`, and `JUMPV` address only `JUMPDEST` instructions. + +>4b `JUMPSUB` and `JUMPSUBV` address only `BEGINSUB` instructions. + +>4c `JUMP` instructions do not address instructions outside of the subroutine they occur in. + +We have two new conditions on execution to ensure consistent use of the stack by subroutines: +>6 For `JUMPSUB` and `JUMPSUBV` the frame size is at least the `n_args` of the `BEGINSUB`(s) to jump to. + +>7 For `RETURNSUB` the frame size is equal to the `n_results` of the enclosing `BEGINSUB`. + +Finally, we have one condition that prevents pathological uses of the stack: +>8 For every instruction in the code the frame size is constant. + +In practice, we must test at runtime for conditions 1 and 2 - sufficient gas and sufficient stack. We don’t know how much gas there will be, we don’t know how deep a recursion may go, and analysis of stack depth even for non-recursive programs is non-trivial. + +All of the remaining conditions we validate statically. + +## VALIDATION + +Validation comprises two tasks: +* Checking that jump destinations are correct and instructions valid. +* Checking that subroutines satisfy the conditions on control flow and stack use. + +We sketch out these two validation functions in pseudo-C below. To simplify the presentation only the five primitives are handled (`JUMPV` and `JUMPSUBV` would just add more complexity to loop over their vectors), we assume helper functions for extracting instruction arguments from immediate data and managing the stack pointer and program counter, and some optimizations are forgone. + +### Validating jumps + +Validating that jumps are to valid addresses takes two sequential passes over the bytecode - one to build sets of jump destinations and subroutine entry points, another to check that addresses jumped to are in the appropriate sets. +``` + bytecode[code_size] // contains EVM bytecode to validate + is_sub[code_size] // is there a BEGINSUB at PC? + is_dest[code_size] // is there a JUMPDEST at PC? + sub_for_pc[code_size] // which BEGINSUB is PC in? + + bool validate_jumps(PC) + { + current_sub = PC + + // build sets of BEGINSUBs and JUMPDESTs + for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC)) + { + if instruction is invalid + return false + if instruction is BEGINDATA + return true + if instruction is BEGINSUB + is_sub[PC] = true + current_sub = PC + sub_for_pc[PC] = current_sub + if instruction is JUMPDEST + is_dest[PC] = true + sub_for_pc[PC] = current_sub + } + + // check that targets are in subroutine + for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC)) + { + if instruction is BEGINDATA + break; + if instruction is BEGINSUB + current_sub = PC + if instruction is JUMPSUB + if is_sub[jump_target(PC)] is false + return false + if instruction is JUMPTO or JUMPIF + if is_dest[jump_target(PC)] is false + return false + if sub_for_pc[PC] is not current_sub + return false + } + return true + } +``` +Note that code like this is already run by EVMs to check dynamic jumps, including building the jump destination set every time a contract is run, and doing a lookup in the jump destination set before every jump. + +### Validating subroutines + +This function can be seen as a symbolic execution of a subroutine in the EVM code, where only the effect of the instructions on the state being validated is computed. Thus the structure of this function is very similar to an EVM interpreter. This function can also be seen as an acyclic traversal of the directed graph formed by taking instructions as vertexes and sequential and branching connections as edges, checking conditions along the way. The traversal is accomplished via recursion, and cycles are broken by returning when a vertex which has already been visited is reached. The time complexity of this traversal is O(n-vertices + n-edges) + +The basic approach is to call `validate_subroutine(i, 0, 0)`, for _i_ equal to the first instruction in the EVM code through each `BEGINDATA` offset. `validate_subroutine()` traverses instructions sequentially, recursing when `JUMP` and `JUMPI` instructions are encountered. When a destination is reached that has been visited before it returns, thus breaking cycles. It returns true if the subroutine is valid, false otherwise. + +``` + bytecode[code_size] // contains EVM bytecode to validate + frame_size[code_size ] // is filled with -1 + + // we validate each subroutine individually, as if at top level + // * PC is the offset in the code to start validating at + // * return_pc is the top PC on return stack that RETURNSUB returns to + // * at top level FP = 0, so SP is both the frame size and the stack size + validate_subroutine(PC, return_pc, SP) + { + // traverse code sequentially, recurse for jumps + while true + { + instruction = bytecode[PC] + + // if frame size set we have been here before + if frame_size[PC] >= 0 + { + // check for constant frame size + if instruction is JUMPDEST + if SP != frame_size[PC] + return false + + // return to break cycle + return true + } + frame_size[PC] = SP + + // effect of instruction on stack + n_removed = removed_items(instructions) + n_added = added_items(instruction) + + // check for stack underflow + if SP < n_removed + return false + + // net effect of removing and adding stack items + SP -= n_removed + SP += n_added + + // check for stack overflow + if SP > 1024 + return false + + if instruction is STOP, RETURN, SUICIDE or BEGINDATA + return true + + // violates single entry + if instruction is BEGINSUB + return false + + // return to top or from recursion to JUMPSUB + if instruction is RETURNSUB + break; + + if instruction is JUMPSUB + { + // check for enough arguments + sub_pc = jump_target(PC) + if SP < n_args(sub_pc) + return false + return true + } + + // reset PC to destination of jump + if instruction is JUMPTO + { + PC = jump_target(PC) + continue + } + + // recurse to jump to code to validate + if instruction is JUMPIF + { + if not validate_subroutine(jump_target(PC), return_pc, SP) + return false + } + + // advance PC according to instruction + PC = advance_pc(PC) + } + + // check for right number of results + if SP != n_results(return_pc) + return false + return true + } +``` + +### COSTS & CODES + +All of the instructions are O(1) with a small constant, requiring just a few machine operations each, whereas a `JUMP` or `JUMPI` must do an O(log n) binary search of an array of `JUMPDEST` offsets before every jump. With the cost of `JUMPI` being _high_ and the cost of `JUMP` being _mid_, we suggest the cost of `JUMPV` and `JUMPSUBV` should be _mid_, `JUMPSUB` and `JUMPIF` should be _low_, and`JUMPTO` should be _verylow_. Measurement will tell. + +We tentatively suggest the following opcodes: +``` +0xB0 JUMPTO +0xB1 JUMPIF +0XB2 JUMPSUB +0xB4 JUMPSUBV +0xB5 BEGINSUB +0xB6 BEGINDATA +0xB8 RETURNSUB +0xB9 PUTLOCAL +0xBA GETLOCAL +``` + +### GETTING THERE FROM HERE + +These changes would need to be implemented in phases at decent intervals: +>1 If this EIP is accepted, invalid code should be deprecated. Tools should stop generating invalid code, users should stop writing it, and clients should warn about loading it. + +>2 A later hard fork would require clients to place only valid code on the block chain. Note that despite the fork old EVM code will still need to be supported indefinitely. + +If desired, the period of deprecation can be extended indefinitely by continuing to accept code not versioned as new - but without validation. That is, by delaying step 2. Since we must continue to run old code this is not technically difficult. + +Implementation of this proposal need not be difficult, At the least, interpreters can simply be extended with the new opcodes and run unchanged otherwise. The new opcodes require only stacks for the frame pointers and return offsets and the few pushes, pops, and assignments described above. JIT code can use native calls. Further optimizations include minimizing runtime checks for exceptions and taking advantage of validated code wherever possible. diff --git a/EIPS/eip-649.md b/EIPS/eip-649.md new file mode 100644 index 00000000..e2adda47 --- /dev/null +++ b/EIPS/eip-649.md @@ -0,0 +1,74 @@ +## Preamble + + EIP: 649 + Title: Metropolis Difficulty Bomb Delay and Block Reward Reduction + Authors: Afri Schoedon, Vitalik Buterin + Type: Standard Track + Category: Core + Status: Final + Created: 2017-06-21 + Replaces: 186 + +## Simple Summary +The average block times are increasing due to the difficulty bomb (also known as the "_ice age_") slowly accelerating. This EIP proposes to delay the difficulty bomb for approximately one and a half year and to reduce the block rewards with the Byzantium fork, the first part of the Metropolis fork. + +## Abstract +Starting with `BYZANTIUM_FORK_BLKNUM` the client will calculate the difficulty based on a fake block number suggesting the client that the difficulty bomb is adjusting around 3 million blocks later than previously specified with the Homestead fork. Furthermore, block rewards will be adjusted to a base of 3 ETH, uncle and nephew rewards will be adjusted accordingly. + +## Motivation +The Casper development and switch to proof-of-stake is delayed, the Ethash proof-of-work should be feasible for miners and allow sealing new blocks every 15 seconds on average for another one and a half years. With the delay of the ice age, there is a desire to not suddenly also increase miner rewards. The difficulty bomb has been known about for a long time and now it's going to stop from happening. In order to maintain stability of the system, a block reward reduction that offsets the ice age delay would leave the system in the same general state as before. Reducing the reward also decreases the likelihood of a miner driven chain split as Ethereum approaches proof-of-stake. + +## Specification +#### Relax Difficulty with Fake Block Number +For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula: + + fake_block_number = max(0, block.number - 3_000_000) if block.number >= BYZANTIUM_FORK_BLKNUM else block.number + +#### Adjust Block, Uncle, and Nephew rewards +To ensure a constant Ether issuance, adjust the block reward to `new_block_reward`, where + + new_block_reward = 3_000_000_000_000_000_000 if block.number >= BYZANTIUM_FORK_BLKNUM else block.reward + +(3E18 wei, or 3,000,000,000,000,000,000 wei, or 3 ETH). + +Analogue, if an uncle is included in a block for `block.number >= BYZANTIUM_FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is + + new_uncle_reward = (8 - k) * new_block_reward / 8 + +This is the existing pre-Metropolis formula for uncle rewards, simply adjusted with `new_block_reward`. + +The nephew reward for `block.number >= BYZANTIUM_FORK_BLKNUM` is + + new_nephew_reward = new_block_reward / 32 + +This is the existing pre-Metropolis formula for nephew rewards, simply adjusted with `new_block_reward`. + +## Rationale +This will delay the ice age by 42 million seconds (approximately 1.4 years), so the chain would be back at 30 second block times at the end of 2018. An alternate proposal was to add special rules to the difficulty calculation to effectively _pause_ the difficulty between different blocks. This would lead to similar results. + +This was previously discussed at All Core Devs Meeting [#09](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%209.md#metropolis-timing-and-roadmap-discussion), [#12](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2012.md#5-metropolis-update), [#13](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2013.md#3-eip-186-reduce-eth-issuance-before-proof-of-stake-hudson), and [#14](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2014.md#1-eip-186-reduce-eth-issuance-before-proof-of-stake-core-devs). Consensus on the specification was achieved in All Core Devs Meeting [#19](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2019.md) and specification drafted in EIP issue [#649](https://github.com/ethereum/EIPs/issues/649). It was decided to replace EIP [#186](https://github.com/ethereum/EIPs/issues/186) and include the block reward reduction along with the difficulty bomb delay in All Core Devs Meeting [#20](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2020.md) and [#21](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2021.md); accepted in [#22](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2022.md). + +## Backwards Compatibility +This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It's suggested to include this EIP in the first of the two Metropolis hard-forks, the _Byzantium_ fork. + +## Test Cases +Test cases exist in ethereum/tests [#269](https://github.com/ethereum/tests/pull/269). + +## Implementation +The following clients implemented EIP-649: + +- Geth [#15028](https://github.com/ethereum/go-ethereum/pull/15028) +- Parity [#5855](https://github.com/paritytech/parity/pull/5855) +- EthereumJ [#927](https://github.com/ethereum/ethereumj/pull/927) +- Cpp-Ethereum [#4050](https://github.com/ethereum/cpp-ethereum/issues/4050) +- PyEthereum [#383](https://github.com/ethereum/pyethereum/pull/383) + +The Yellow Paper implements EIP-649 in [#333](https://github.com/ethereum/yellowpaper/pull/333). + +Other notable implementations: + +- Eth-Isabelle [#459](https://github.com/pirapira/eth-isabelle/issues/459) +- Py-EVM [#123](https://github.com/pipermerriam/py-evm/pull/123) + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-658.md b/EIPS/eip-658.md new file mode 100644 index 00000000..09afc15e --- /dev/null +++ b/EIPS/eip-658.md @@ -0,0 +1,31 @@ +## Preamble + + EIP: 658 + Title: Embedding transaction status code in receipts + Author: Nick Johnson + Type: Standard Track + Category Core + Status: Final + Created: 2017-06-30 + Requires: 140 + Replaces: 98 + + +## Abstract +This EIP replaces the intermediate state root field of the receipt with a status code indicating if the top-level call succeeded or failed. + +## Motivation +With the introduction of the REVERT opcode in EIP140, it is no longer possible for users to assume that a transaction failed iff it consumed all gas. As a result, there is no clear mechanism for callers to determine whether a transaction succeeded and the state changes contained in it were applied. + +Full nodes can provide RPCs to get a transaction return status and value by replaying the transaction, but fast nodes can only do this for nodes after their pivot point, and light nodes cannot do this at all, making a non-consensus solution impractical. + +Instead, we propose to replace the intermediate state root, already obsoleted by EIP98, with the return status (1 for success, 0 for failure). This both allows callers to determine success status, and remedies the previous omission of return data from the receipt. + +## Specification +For blocks where block.number >= BYZANTIUM_FORK_BLKNUM, the intermediate state root is replaced by a status code, 0 indicating failure (due to any operation that can cause the transaction or top-level call to revert) and 1 indicating success. + +## Rationale +This constitutes a minimal possible change that permits fetching the success/failure state of transactions, preserving existing capabilities with minimum disruption or additional work for Metropolis. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-7.md b/EIPS/eip-7.md index edfaaf13..f9f5059f 100644 --- a/EIPS/eip-7.md +++ b/EIPS/eip-7.md @@ -2,7 +2,7 @@ EIP: 7 Title: DELEGATECALL Author: Vitalik Buterin - Status: Accepted + Status: Final Type: Homestead feature Created: 2015-11-15 diff --git a/EIPS/eip-706.md b/EIPS/eip-706.md new file mode 100644 index 00000000..638b1564 --- /dev/null +++ b/EIPS/eip-706.md @@ -0,0 +1,199 @@ +## Preamble + + EIP: 706 + Title: DEVp2p snappy compression + Author: Péter Szilágyi + Type: Standard Track + Category: Networking + Status: Final + Created: 2017-09-07 + +## Abstract +The base networking protocol (DEVp2p) used by Ethereum currently does not employ any form of compression. This results in a massive amount of bandwidth wasted in the entire network, making both initial sync as well as normal operation slower and laggier. + +This EIP proposes a tiny extension to the DEVp2p protocol to enable [Snappy compression](https://en.wikipedia.org/wiki/Snappy_(compression)) on all message payloads after the initial handshake. After extensive benchmarks, results show that data traffic is decreased by 60-80% for initial sync. You can find exact numbers below. + +## Motivation +Synchronizing the Ethereum main network (block 4,248,000) in Geth using fast sync currently consumes 1.01GB upload and 33.59GB download bandwidth. On the Rinkeby test network (block 852,000) it's 55.89MB upload and 2.51GB download. + +However, most of this data (blocks, transactions) are heavily compressable. By enabling compression at the message payload level, we can reduce the previous numbers to 1.01GB upload / 13.46GB download on the main network, and 46.21MB upload / 463.65MB download on the test network. + +The motivation behind doing this at the DEVp2p level (opposed to eth for example) is that it would enable compression for all sub-protocols (eth, les, bzz) seamlessly, reducing any complexity those protocols might incur in trying to individually optimize for data traffic. + +## Specification +Bump the advertised DEVp2p version number from `4` to `5`. If during handshake, the remote side advertises support only for version `4`, run the exact same protocol as until now. + +If the remote side advertises a DEVp2p version `>= 5`, inject a Snappy compression step right before encrypting the DEVp2p message during sending: + + * A message consists of `{Code, Size, Payload}` + * Compress the original payload with Snappy and store it in the same field. + * Update the message size to the length of the compressed payload. + * Encrypt and send the message as before, oblivious to compression. + +Similarly to message sending, when receiving a DEVp2p v5 message from a remote node, insert a Snappy decompression step right after the decrypting the DEVp2p message: + +* A message consists of `{Code, Size, Payload}` + * Decrypt the message payload as before, oblivious to compression. + * Decompress the payload with Snappy and store it in the same field. + * Update the message size to the length of the decompressed payload. + +Important caveats: + + * The handshake message is **never** compressed, since it is needed to negotiate the common version. + * Snappy framing is **not** used, since the DEVp2p protocol already message oriented. + +*Note: Snappy supports uncompressed binary literals (up to 4GB) too, leaving room for fine-tuned future optimisations for already compressed or encrypted data that would have no gain of compression (Snappy usually detects this case automatically).* + +### Avoiding DOS attacks + +Currently a DEVp2p message length is limited to 24 bits, amounting to a maximum size of 16MB. With the introduction of Snappy compression, care must be taken not to blindy decompress messages, since they may get significantly larger than 16MB. + +However, Snappy is capable of calculating the decompressed size of an input message without inflating it in memory (*[the stream starts with the uncompressed length up to a maximum of `2^32 - 1` stored as a little-endian varint](https://github.com/google/snappy/blob/master/format_description.txt#L20)*). This can be used to discard any messages which decompress above some threshold. **The proposal is to use the same limit (16MB) as the threshold for decompressed messages.** This retains the same guarantees that the current DEVp2p protocol does, so there won't be surprises in application level protocols. + +## Alternatives (discarded) + +**Alternative solutions to data compression that have been brought up and discarded are:** + +Extend protocol `xyz` to support compressed messages versus doing it at DEVp2p level: + + * **Pro**: Can be better optimized when to compress and when not to. + * **Con**: Mixes in transport layer encoding into application layer logic. + * **Con**: Makes the individual message specs more convoluted with compression details. + * **Con**: Requires cross client coordination on every single protocol, making the effor much harder and repeated (eth, les, shh, bzz). + +Introduce seamless variations of protocol such as `xyz` expanded with `xyz-compressed`: + + * **Pro**: Can be done (hacked in) without cross client coordination. + * **Con**: Litters the network with client specific protocol announces. + * **Con**: Needs to be specced in an EIP for cross interoperability anyway. + +**Other ideas that have been discussed and discarded:** + +Don't explicitly limit the decompressed message size, only the compressed one: + + * **Pro**: Allows larger messages to traverse through DEVp2p. + * **Con**: Upper layer protocols need to check and discard large messages. + * **Con**: Needs lazy decompression to allow size limitations without DOS. + +## Backwards Compatibility +This proposal is fully backward compatible. Clients upgrading to the proposed DEVp2p protocol version `5` should still support skipping the compression step for connections that only advertise version `4` of the DEVp2p protocol. + +## Implementation +You can find a reference implementation of this EIP in https://github.com/ethereum/go-ethereum/pull/15106. + +## Test vectors + +There is more than one valid encoding of any given input, and there is more than one good internal compression algorithm within Snappy when trading off throughput for output size. As such, different implementations might produce slight variations in the compressed form, but all should be cross compatible between each other. + +As an example, take hex encoded RLP of block #272621 from the Rinkeby test network: [block.rlp (~3MB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.rlp). + + * Encoding the raw RLP via [Go's Snappy library](https://github.com/golang/snappy) yields: [block.go.snappy (~70KB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.go.snappy). + * Encoding the raw RLP via [Python's Snappy library](https://github.com/andrix/python-snappy) yields: [block.py.snappy (~70KB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.py.snappy). + +You can verify that an encoded binary can be decoded into the proper plaintext using the following snippets: + +### Go + +``` +$ go get https://github.com/golang/snappy +``` + +```go +package main + +import ( + "bytes" + "encoding/hex" + "fmt" + "io/ioutil" + "log" + "os" + + "github.com/golang/snappy" +) + +func main() { + // Read and decode the decompressed file + plainhex, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + log.Fatalf("Failed to read decompressed file %s: %v", os.Args[1], err) + } + plain, err := hex.DecodeString(string(plainhex)) + if err != nil { + log.Fatalf("Failed to decode decompressed file: %v", err) + } + // Read and decode the compressed file + comphex, err := ioutil.ReadFile(os.Args[2]) + if err != nil { + log.Fatalf("Failed to read compressed file %s: %v", os.Args[2], err) + } + comp, err := hex.DecodeString(string(comphex)) + if err != nil { + log.Fatalf("Failed to decode compressed file: %v", err) + } + // Make sure they match + decomp, err := snappy.Decode(nil, comp) + if err != nil { + log.Fatalf("Failed to decompress compressed file: %v", err) + } + if !bytes.Equal(plain, decomp) { + fmt.Println("Booo, decompressed file does not match provided plain text!") + return + } + fmt.Println("Yay, decompressed data matched provided plain text!") +} +``` + +``` +$ go run main.go block.rlp block.go.snappy +Yay, decompressed data matched provided plain text! + +$ go run main.go block.rlp block.py.snappy +Yay, decompressed data matched provided plain text! +``` + +### Python + +```bash +$ pip install python-snappy +``` + +```py +import snappy +import sys + +# Read and decode the decompressed file +with open(sys.argv[1], 'rb') as file: + plainhex = file.read() + +plain = plainhex.decode("hex") + +# Read and decode the compressed file +with open(sys.argv[2], 'rb') as file: + comphex = file.read() + +comp = comphex.decode("hex") + +# Make sure they match +decomp = snappy.uncompress(comp) +if plain != decomp: + print "Booo, decompressed file does not match provided plain text!" +else: + print "Yay, decompressed data matched provided plain text!" +``` + +``` +$ python main.py block.rlp block.go.snappy +Yay, decompressed data matched provided plain text! + +$ python main.py block.rlp block.py.snappy +Yay, decompressed data matched provided plain text! +``` + +## References + + * Snappy website: https://google.github.io/snappy/ + * Snappy specification: https://github.com/google/snappy/blob/master/format_description.txt + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-8.md b/EIPS/eip-8.md index 33faeed3..11e8efcf 100644 --- a/EIPS/eip-8.md +++ b/EIPS/eip-8.md @@ -3,7 +3,7 @@ EIP: 8 Title: devp2p Forward Compatibility Requirements for Homestead Author: Felix Lange - Status: Accepted + Status: Final Type: Standards Track Layer: Networking Created: 2015-12-18 diff --git a/EIPS/eip-EIPS/eip-616.md b/EIPS/eip-EIPS/eip-616.md new file mode 100644 index 00000000..91f196a5 --- /dev/null +++ b/EIPS/eip-EIPS/eip-616.md @@ -0,0 +1,141 @@ +``` +EIP: +Title: SIMD Operations for the EVM +Author: Greg Colvin, greg@colvin.org +Type: Standard Track +Category: Core +Status: Draft +Created: 2017-04-25 +``` + +## ABSTRACT + +A proposal to provide Single Instruction Multiple Data types and operations for the Ethereum Virtual Machine, making full use of the 256-bit wide EVM stack items, and offering substantial performance gains for both vector and scalar operations. + +## MOTIVATION + +Most all modern CPUs include SIMD hardware that operates on wide registers of data, applying a Single Instruction to Multiple Data lanes in parallel, where lanes divide a register into a vector of scalar elements of equal size. This model is an excellent fit for the wide stack items of the EVM, offering substantial performance boosts for operations that can be expressed as parallel operations on vectors of scalars. For some examples, a brief literature search finds SIMD speedups of +* up to 7X for [SHA-512](http://keccak.noekeon.org/sw_performance.html) +* 4X for [elliptic curve scalar multiplication](http://link.springer.com/chapter/10.1007/3-540-45439-X_16) +* 3X to 4X for [BLAKE2b](http://github.com/minio/blake2b-simd) +* up to 3X for [OpenSSL](https://software.intel.com/en-us/articles/improving-openssl-performance) +* 2X to 3X for [elliptic curve modular multiplication](http://ieee-hpec.org/2013/index_htm_files/24-Simd-acceleration-Pabbuleti-2886999.pdf) +* 1.7X to 1.9X for [SHA-256](https://github.com/minio/sha256-simd) +* 1.3X for [RSA encryption](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.738.1218&rep=rep1&type=pdf) + +## SPECIFICATION + +### Encoding + +We propose a simple encoding of SIMD operations as extended two-byte codes. The first byte is the opcode, and the second byte is the SIMD type: scalar type, lane width, and number of elements. + + N bits | Field +-|- +8 | opcode +1 | scalar type: 0 = unsigned integer, 1 = IEEE float +1 | reserved: 0 +2 | lane width: log base 2 of the number of bytes, as an MSB first integer +1 | reserved: 0 +3 | element count: log base 2 of the number of lanes, as an MSB first integer + +Thus we can specify SIMD types with unsigned integer lanes from 8 to 64 bits in vectors of 32 to 2 lanes, respectively. Floating point lanes however support only 32- and 64-bit IEEE floating point. And a type of _0x7F_ represents a normal 256-bit EVM integer. + +_Note that when the element count is one the operation is on one scalar, so this specification also provides for native operations on single scalars of native sizes._ + +_Note that floating point operations are **not** proposed for inclusion in the initial release, but we considered it important to reserve code space for possible future expansion._ + +### Semantics + +We define the following extended versions of the EVM's arithmetic, logic, and comparison operations. As with the normal versions, they consume their arguments from the stack and place their results on the stack, except that their arguments are vectors rather than scalars. + +lo\hi | B | C +-|-|- +0| | XLT +1| XADD | XGT +2| XMUL | XSLT +3| XSUB | XSGT +4| XDIV | XEQ +5| XSDIV | XISZERO +6| XMOD | XAND +7| XSMOD | XOR +8| | XXOR +9| | XNOT +A| | XINDEX +B| | XSHL +C| | XSHR +D| | XSAR +E| XCAST | XROL +F| XSHUFFLE | XROR + +Except for XSHUFFLE, XCAST, and XINDEX all the extended operations on unsigned integer values have the same semantics as the corresponding operations for codes 01 through 1F, except that the modulus varies by scalar type and the operations are applied pair-wise to the elements of the source operands to compute the destination elements. _The source operands must have the same element type and number of elements._ E.g. +``` +PUSH uint8[1, 2, 3] +PUSH uint8[4, 5, 6] +XADD +``` +leaves +``` +uint8[5, 7, 9] +``` +on the stack. + +XSHUFFLE takes two vectors on the stack: a vector to permute and a permutation mask. E.g. +``` +PUSH uint64[4, 5, 6, 0] +PUSH uint8[2, 0, 1, 3] +SHUFFLE +``` +leaves +``` +uint64[6, 4, 5 , 0] +``` +on the stack. The mask must have integral type, and the same number of elements as the source vector. + +The second byte of the XCAST opcode is applied to the item on the stack to create a new vector of the specified type. Elements are converted according to the usual C conventions, missing elements are set to zero, and extra elements are discarded. If the stack item is not a vector it is converted to a vector by taking its bits least-significant-bit first and copying them into the corresponding bits of each element, least-significant-element first. Again, excess data is truncated and missing data is 0-filled. Vectors are converted to 256-bit EVM integers via the reverse process., with elements that are floating point NANs normalized to all bits on. + +_Note that MLOAD and MSTORE are valid only on 256-bit EVM integers. For SIMD vectors an XCAST is needed after a load and before a store to convert vectors to and from 256-bit integers._ + +XINDEX has the same semantics as BYTE, except that individual elements of the vector are indexed. + +Floating point values follow IEEE 754 semantics. Since those are not defined for shifting and rotating those operations are defined here as having no effect. + +Extended operations other than XSHUFFLE and XCAST are only valid on vectors of the same SIMD type. This can be validated at contract creation time, or else checked at runtime. + +### Subroutines + +If [EIP 187](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-187.md) is accepted a typpe-safe syntax for declaring subroutines taking vector arguments will be needed. + +* `BEGINSUBX n_args, arg_types... n_results, result_types...` +marks the **single** entry to a subroutine. `n_args` items are taken off of the stack at entry to, and `n_results` items are placed on the stack at return from the subroutine. `n_args` and `n_results` are given as one immediate byte each. The `arg_types` and `result_types` are given in the same encoding as second byte of the SIMD opcodes, and must match the values on the stack. The bytecode for a subroutine ends at the next `BEGINSUB`, `BEGINSUBX` or `BEGINDATA` instruction or at the end of the bytecode. + +## RATIONALE + +Currently, the lowest common denominator for SIMD hardware (e.g. Intel SSE2 and ARM Neon) is 16-byte registers supporting integer lanes of 1, 2, 4, and 8 bytes, and floating point lanes of 4 and 8 bytes. More recent SIMD hardware (e.g. Intel AVX) supports 32-byte registers, and EVM stack items are also 32 bytes wide. The limits above derive from these numbers, assuring that EVM code is within the bounds of available hardware - and the reserved bits provide room for growth. + +For most modern languages (including Rust, Python, Go, Java, and C++) compilers can do a good job of generating SIMD code for parallelizable loops, and/or there are intrinsics or libraries available for explicit access to SIMD hardware. So a portable software implementation will likely provide good use of the hardware on most platforms, and intrinsics or libraries can be used as available and needed. Thus we can expect these operations to take about the same (or for 256-bit vectors on 128-bit hardware up to twice) the time to execute regardless of element size or number of elements. + +### Gas + +One motivation for these operations, besides taking full advantage of the hardware, is assigning lower gas costs for operations on smaller scalars. + +On a machine with 64-bit registers the standard algorithms from Knuth's [Art of Computer Programming](http://library.aceondo.net/ebooks/Computer_Science/algorithm-the_art_of_computer_programming-knuth.pdf) require 32-bit digits, using the upper half of a register for overflows, so for 256-bit values N=8 digits are needed, and for 64-bit values N=2 digits are needed. The cycle counts for these algorithms are: + +operation | cycles | N = 2 | N = 4 | N = 8 +-|-|-|-|- +add | 10 _N_ + 6 | 26 | 46 | 86 +subtract | 12 _N_ + 3 |27 | 51 | 99 +multiply | 28 _N_**2 + 11 _N_ + 3 | 137 | 495 |1883 +divide | 30 _N_**2 + 119 _N_ + 111 | 469 | 1067 | 2983 + +The remaining operations are of about the same complexity as addition and subtraction, or less. Given that JUMPDEST is a no-op, and is assigned a gas price of 1, this can be taken as the overhead of the interpreter. All of the arithmetic operations are assigned the same gas price of 5, for a remaining runtime of 4. The interpreter loop itself takes about 6 to 8 C instructions, so ADD and SUB are reasonably priced, but MUL is some 5 to 21 times slower than ADD or SUB, and DIV is some 18 to 35 times slower, so they are clearly mispriced. + +By comparison, on most [Intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide) and [ARM](https://developer.arm.com/docs/100166_0001/latest/programmers-model/instruction-set-summary/table-of-processor-instructions) SIMD units instructions take approximately the following cycle counts, independent of register width. + +operation | Intel cycles | ARM cycles | gas +-|-|-|- +add | .5 | 1 | 1 +subtract | .5 | 1 | 1 +multiply | 2 | 1 | 1 +divide | 10 | 12 | 2 + +Since all but the divide operation take fewer cycles than the interpreter overhead they are assigned the minimal cost of 1. Division takes slightly more, and is assigned a cost of 2. diff --git a/EIPS/eip-XXX.md b/EIPS/eip-XXX.md deleted file mode 100644 index dfbfe5a0..00000000 --- a/EIPS/eip-XXX.md +++ /dev/null @@ -1,526 +0,0 @@ -
-  EIP: draft
-  Title: Ethereum Domain Name Service - Specification
-  Author: Nick Johnson 
-  Status: Draft
-  Type: Informational
-  Created: 2016-04-04
-
- -Abstract -======== -This draft EIP describes the details of the Ethereum Name Service, a proposed protocol and ABI definition that provides flexible resolution of short, human-readable names to service and resource identifiers. This permits users and developers to refer to human-readable and easy to remember names, and permits those names to be updated as necessary when the underlying resource (contract, content-addressed data, etc) changes. - -The goal of domain names is to provide stable, human-readable identifiers that can be used to specify network resources. In this way, users can enter a memorable string, such as 'vitalik.wallet' or 'www.mysite.swarm', and be directed to the appropriate resource. The mapping between names and resources may change over time, so a user may change wallets, a website may change hosts, or a swarm document may be updated to a new version, without the domain name changing. Further, a domain need not specify a single resource; different record types allow the same domain to reference different resources. For instance, a browser may resolve 'mysite.swarm' to the IP address of its server by fetching its A (address) record, while a mail client may resolve the same address to a mail server by fetching its MX (mail exchanger) record. - -Motivation -========== -Existing [specifications](https://github.com/ethereum/wiki/wiki/Registrar-ABI) and [implementations](https://ethereum.gitbooks.io/frontier-guide/content/registrar_services.html) for name resolution in Ethereum provide basic functionality, but suffer several shortcomings that will significantly limit their long-term usefulness: - - - A single global namespace for all names with a single 'centralised' resolver. - - Limited or no support for delegation and sub-names/sub-domains. - - Only one record type, and no support for associating multiple copies of a record with a domain. - - Due to a single global implementation, no support for multiple different name allocation systems. - - Conflation of responsibilities: Name resolution, registration, and whois information. - -Use-cases that these features would permit include: - - - Support for subnames/sub-domains - eg, live.mysite.tld and forum.mysite.tld. - - Multiple services under a single name, such as a DApp hosted in Swarm, a Whisper address, and a mail server. - - Support for DNS record types, allowing blockchain hosting of 'legacy' names. This would permit an Ethereum client such as Mist to resolve the address of a traditional website, or the mail server for an email address, from a blockchain name. - - DNS gateways, exposing ENS domains via the Domain Name Service, providing easier means for legacy clients to resolve and connect to blockchain services. - - Programmatic name definition and resolution - for example, providing a service that resolves <content hash>.swarm.tld to a swarm node that can return the content. - -The first two use-cases, in particular, can be observed everywhere on the present-day internet under DNS, and we believe them to be fundamental features of a name service that will continue to be useful as the Ethereum platform develops and matures. - -We propose to draw lessons from the design of the [DNS](https://www.ietf.org/rfc/rfc1035.txt) system, which has been providing name resolution to the internet for over 30 years. Many features apply well to Etherum and can be adapted; others are inapplicable or unwanted and should be discarded. - -The normative parts of this document does not specify an implementation of the proposed system; its purpose is to document a protocol that different resolver implementations can adhere to in order to facilitate consistent name resolution. An appendix provides sample implementations of resolver contracts and libraries, which should be treated as illustrative examples only. - -Likewise, this document does not attempt to specify how domains should be registered or updated, or how systems can find the owner responsible for a given domain. Registration is the responsibility of registrars, and is a governance matter that will necessarily vary between top-level domains. We propose a design for the governance of the top level resolver in a separate document (TBD). - -Updating of domain records can also be handled separately from resolution. Some systems, such as swarm, may require a well defined interface for updating domains, in which event we anticipate the development of a standard for this. Finally, finding the responsible parties of a domain is the task of a whois system, which can be specified separately, even if resolvers typically implement both protocols. - -Specification -============= -Overview --------- -The ENS, or Ethereum Name Service, proposed here, borrows where appropriate from the Domain Name System used to resolve domain names on the internet. This is done both because their requirements are similar, and thus we can take advantage of lessons learned from 30 years of accumulated experience serving as the Internet's name resolution system, and because it permits easier interoperability between the two systems. - -Although this document aims to be as self contained as possible, in the interest of avoiding duplication, we make references to features of the DNS specification. [RFC1035](https://www.ietf.org/rfc/rfc1035.txt), which provides the basic definition of the domain name system, may prove useful reading alongside this document. - -ENS is hierarchial, with more general parts on the left, and more specific parts on the right. In the domain 'www.example.com', 'com' is the top-level domain, while 'www' specifies a sub-domain. Unlike DNS, names are relative; each resolver is passed one label to resolve, and it performs a lookup and returns its record for that label. This means that rather than forming a tree, the set of deployed names may form a graph; nodes can link to each other at any depth in the hierarchy. The resolution process is described in detail below. - -Although we expect most users to converge on a common root-level resolver, the system permits the existence of 'alternate roots', which provide their own set of top-level domains, which may potentially overlap with those exposed by other root resolvers. Due to the relative nature of name resolution in ENS, users may point to a "local resolver"; a name that resolves internally as "mysite.corp" may be exposed to external users as "mysite.corp.company.com". - -Resolvers exist as contracts in the Ethereum blockchain; this allows contracts to perform name resolution, in addition to allowing use by DApps. We expect both to use ENS for resolving names to contracts and to content hashes. - -Name Syntax ------------ -ENS names must conform to the following syntax: - -
<domain> ::= <label> | <domain> "." <label>
-<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
-<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
-<let-dig-hyp> ::= <let-dig> | "-"
-<let-dig> ::= <letter> | <digit>
-<letter> ::= any one of the 52 alphabetic characters A through Z in
-upper case and a through z in lower case
-<digit> ::= any one of the ten digits 0 through 9
-
- -In short, names consist of a series of dot-separated labels. Each label must start with a letter, and end with a letter or a digit. Intermediate letters may be letters, digits, or hyphens. - -Note that while upper and lower case letters are allowed in names, no significance is attached to case. Two names with different case but identical spelling should be treated as identical. - -Labels and domains may be of any length, but for compatibility with legacy DNS, it is recommended that labels be restricted to no more than 64 characters each, and complete ENS names to no more than 255 characters. - -Names are restricted to ASCII on the basis that the existing punycode and nameprep systems exist to allow browsers and other tools to support unicode domain names. Although it is tempting to fully support UTF-8 directly in the system, this would require resolvers to implement generalized unicode case folding, which imposes an undue burden on contracts, which have to limit their gas consumption for callers. - -ENS Structure -------------- -The ENS hierarchy is conceptually structured as a tree. Each node in the tree represents a part of a name. A tree node may have child nodes, representing subdomains, and resource records (RRs), containing mapping information from names to other resources. - -A (simple) example tree might look something like this: - - (root node) - - "swarm" - - "mysite" - - RR: "CHASH" => "0x12345678" - - "othersite" - - RR: "CHASH" => "0x23456789" - - "subdomain" - - RR: "CHASH" => "0x34567890" - - "eth - - "bob" - - RR: "HA" => "0x45678901" - - RR: "HA" => "0x56789012" - - RR: "CHASH" => "0x67890123" - -Each node is uniquely identified by a Node ID and a resolver address. Node IDs are allocated arbitrarily by resolvers, and make it possible to resolve many different parts of the ENS hierarchy using a single resolver instance. Any of the above nodes may be hosted by separate resolvers; resolvers host "glue records" that allow clients to follow the links from one resolver to another when resolving a name. - -Since any node can point to any other node, the ENS hierarchy is in fact a graph rather than a tree; it can even be cyclic, though in practical cases will generally not be. The structure of ENS makes it easy for organisations to define their own name (sub-)hierarchies, delegating parts of the namespace as they see fit. - -Resolution Process ------------------- -Before being passed to resolvers, ENS names are preprocessed. The name is divided into labels, starting with the rightmost one, and each label is first folded to lower-case, then hashed with SHA3-256. So, the domain "subdomain.othersite.swarm", after processing, becomes the sequence of labels [sha3("swarm"), sha3("othersite"), sha3("subdomain")]. - -Name resolution is performed iteratively. The client first performs `findResolver` query on the root resolver, passing it the hash of the rightmost label. The root resolver looks up its internal node for the last domain component, sha3("swarm") in this example. If the record, which consists of a (node ID, resolver address) tuple exists, it returns it, and the client repeats the process for the resolver specified in that record with the next part of the domain. If at any point the record does not exist, an immediate response of NXDOMAIN (No such domain) is returned. - -Once this procedure has been executed for all domain components, the final resolver is sent a `resolve` query for the requested record type. - -Resolvers are specified with a 160 bit address, specifying the address of the Ethereum contract acting as the resolver, and a 96 bit node ID. Node IDs are local to each resolver, and allow resolvers to host multiple independent subtrees. By convention, a root resolver's main tree has node ID of 0, but this is not mandatory. - -RR Definitions --------------- -### Format -A Resource Record is the base unit of storage and retrieval in the ENS. Each resource record consists of: - - NAME - the name to which this record pertains. - - TYPE - one of the RR type codes, specifying the type of resource being addressed. - - TTL - the duration, in seconds, that the record may be cached. - - RDATA - the data associated with this record, whose format depends on TYPE and (potentially) CLASS. - -### TYPE values -TYPE fields specify the nature of the record. ENS uses the same definitions of types as DNS, a registry of which can be seen [here](http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4). - -Until standardized TYPE values are assigned, the following temporary TYPEs are employed for new record types: - - CHASH - Provides the content-hash of a document, retrievable using a content-addressed storage system. - - HA - Provides the hash-based address of an entity, such as a blockchain account address. - -Unlike DNS, which uses type IDs from a 16 bit range to identify record types, ENS encodes types directly as ASCII strings in a bytes32 argument. Strings are left-aligned and padded with 0 bytes. - -### QTYPE values -QTYPE fields appear in the question part of a query. QTYPES are a superset of TYPEs, hence all TYPEs are valid QTYPEs. EIP defines the same set of QTYPEs as DNS. - -New RRs -------- -### CHASH RDATA format -
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-|                                               |
-/                                               /
-/                   Hash value                  /
-|                                               |
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- -Where: - - Hash value - the binary value of a hash function applied to the content being referenced. - -A CHASH record serves as a means to identify a document by its hash, permitting lookup in hash-named datastores such as Swarm. - -### HA RDATA format -
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-|                                               |
-/                                               /
-/                   Hash value                  /
-|                                               |
-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- -Where: - - Hash value - the binary value of the hash-based address. - -A HA record specifies a hash-based address, such as an Ethereum wallet address. - -API ---- -### findResolver -This method requests that the resolver return the address and Node ID of the resolver responsible for the specified label. - -An ENS resolver must implement an API conforming to the following signature, under the standard [Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI): - -
function findResolver(bytes12 node, bytes32 label) returns (uint16 rcode, uint32 ttl, bytes12 rnode, address raddress);
- -Where: - - node - The 96-bit node ID from which to begin the query. By convention, root resolvers start their main tree at node 0. - - label - The sha3 hash of a domain label, as described in "Resolution Process". - - rcode - Response code, as defined in DNS. - - ttl - Duration in seconds that this record may be cached. - - rnode - The Node ID of the resolver. - - raddress - The address of the resolver. - -`ttl` specifies the maximum amount of time a record may be cached for. This is used only by local resolvers and DNS gateways. Contracts that need to resolve names may choose to ignore caching and fetch the record afresh each time the need it, if they expect to handle name resolutions infrequently compared to the expected TTL. - -### resolve -This method requests that the resolver return a name record of the specified record type. - -An ENS resolver must implement an API conforming to the following signature, under the standard [Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI): - -
function resolve(bytes12 node, bytes16 qtype, uint16 index) returns (uint16 rcode, bytes16 rtype, uint32 ttl, uint16 len, bytes32 data);
- -Where: - - node - The 96-bit node ID from which to begin the query. By convention, root resolvers start their main tree at node 0. - - qtype - The query type, a left-aligned zero-padded byte string, as specified by DNS and amended with the CHASH and RA types. - - index - Specifies the index into the array of results to return. Specifying an index that is out of bounds will result in a 0-length response. - - rcode - Response code, as defined in DNS. - - rtype - The DNS TYPE of the returned record. - - ttl - Duration in seconds that this record may be cached. - - len - Length of the returned result, see below. - - data - Result data. - -`qtype` specifies the query type of the query. Unlike DNS, which uses numerical query types, ENS uses the name of the type, such as 'A', 'CHASH', etc. Query types are encoded as ASCII and left aligned (stored in the most significant bits of the 32 byte field). - -`ttl` specifies the maximum amount of time a record may be cached for. This is used only by local resolvers and DNS gateways. Contracts that need to resolve names may choose to ignore caching and fetch the record afresh each time the need it, if they expect to handle name resolutions infrequently compared to the expected TTL. - -`index` permits iteration over multiple records. If a request is made with an index that is out of bounds, a response with a `len` of 0 is returned. Resolvers may return records in an arbitrary order, but the order MUST be consistent within a single block. - -If `len` is 32 or less, the complete record is returned in `data`. If `len` is greater than 32, the result is too large to fit in a bytes32, and `data` instead contains a unique identifier. To fetch the complete record, call `getExtended` (described below) with the identifier. Values with `len` less than 32 are left-aligned (most significant bytes; higher array indexes when treated as an array in Solidity). Since numeric values such as addresses are right-aligned in Solidity, these should be treated as having a length of 32 bytes, regardless of the original data length. - -### getExtended -When a record exceeds 32 bytes in length, an alternative mechanism is provided for fetching the result data, as described above in the description of `resolve`. - -If a resolver can ever return a result of length greater than 32 bytes, it MUST implement getExtended. Resolvers that limit their record size, or only implement record types of fixed length no longer than 32 bytes, need not provide this function. - -
function getExtended(bytes32 id) returns (bytes data);
- -Where: - - id - The unique record identifier returned by a previous call to `resolve`. - - data - The full contents of the requested extended record. - -If the id provided does not exist in the database, the resolver returns an empty byte string. - -Rationale -========= -Gas costs ---------- -Ethereum contracts operate under a very constrained VM, with substantial costs for allocating memory and copying data. This drove a number of tradeoffs designed to retain as much flexibility as possible, while eliminating overhead that would be unnecessary in common name resolution situations: - - `resolve` returns fixed-length records, with a separate API for fetching longer records. This avoids the need to dynamically allocate large buffers, when most common results (to A, CHASH, HA, etc records) will fit in a small fixed-length buffer. - - Name components are preparsed and hashed. This allows name parsing to be done once in common cases, at contract instantiation time, avoiding the high overhead of string manipulation in the EVM, and also permitting names of arbitrary length without the overhead of variable length types. - - DNS's distinction between 'answer records', 'authority records' and 'additional records' has been eliminated, in favor of returning a single record with each call, of whichever type is appropriate, to eliminate unnecessary overhead and repeated calls. - -Complexity reduction --------------------- -Most contracts and DApps have fairly straightforward needs for name resolution. However, past experience with DNS has shown that adding new functionality once widely deployed is difficult to impossible; the immutability of contracts in Ethereum may serve to make this even harder. Thus, we seek to find an acceptable tradeoff, with enough flexibility to allow more sophisticated uses and to provide for future expandability, while not unduly complicating simple use-cases. - -Several features are designed with this in mind. The `getExtended` function call is required only if a resolver may return records greater than 32 bytes in length. Since common record types, such as account/contract addresses and content hashes fit within this size, common resolver implementations may choose to simply not support longer records, reducing implementation complexity. Likewise, local resolvers that do not need to provide the facility to retrieve longer records may choose not to implement this functionality, returning an error if a record is too long. - -Finally, we expect local resolver implementations to mask complexity from the user. Common interfaces will include simple "lookup" functions that parse names into lists of hashes, and potentially cache records internally. Root resolvers may additionally decide to offer simple interfaces compatible with current practice. - -Elimination of DNS CLASS ------------------------- -In addition to TYPE, DNS also defines CLASS, which specifies the type of network the record is for. In practice, this is almost universally 'IN' (Internet). Since we expect this to always be the case for Ethereum-based resolvers, we have omitted CLASS from the nameservice definition. Gateways to the DNS system should assume this value is always 'IN'. - -Caching -------- -Because all resolvers exist as contracts in the blockchain, and all parts of the blockchain state are equally 'close' to each other and to the user, there is little point in supporting recursive lookup by resolvers and local caching for latency reasons. For this reason, and for others outlined above in 'Gas costs', ENS does not support recursive lookups. A `ttl` field is provided because limited caching is still useful in some cases: a contract that is called frequently and always needs to resolve a name may choose to cache it in local storage to reduce the overhead of calling the resolver contracts, and DApps and gateways existing outside the blockchain may find it useful to cache results locally. - -Implementation -============== -Authoritative Resolver ----------------------- -This contract implements a minimal authoritative resolver. The contract 'Resolver' implements the name resolution functionality, while 'OwnedRegistrar' adds functionality allowing the owner to set HA and CHASH records, following the ABI defined for existing global resolvers. It will happily act as authoritative resolver for any domain that's added to it, though naturally those domains will not resolve unless the relevant glue records are present in higher level resolvers. - -A more complete implementation of a leaf authoritative resolver would add support for unsupported features (long records, CNAME) and provide a more sophisticated API for managing the resolver's database, including setting TTLs, multiple records, and other types than HA and CHASH. - -``` -/** - * Basic authoritative resolver implementation. - * - * This resolver supports basic functionality required to conform to the - * ENS specification, but no advanced features. Not supported: - * - Data payloads of over 32 bytes (and thus, the getExtended() call). - */ -contract Resolver { - bytes32 constant TYPE_STAR = "*"; - - // Response codes. - uint16 constant RCODE_OK = 0; - uint16 constant RCODE_FORMAT_ERR = 1; - uint16 constant RCODE_SRVFAIL = 2; - uint16 constant RCODE_NXDOMAIN = 3; - uint16 constant RCODE_NOT_IMPLEMENTED = 4; - uint16 constant RCODE_REFUSED = 5; - - struct RR { - bytes16 rtype; - uint32 ttl; - uint16 len; - bytes32 data; - } - - struct ResolverAddress { - bytes12 nodeId; - address addr; - uint32 ttl; - } - - struct Node { - bool exists; - mapping (bytes32=>ResolverAddress) subnodes; - RR[] records; - } - - mapping (bytes12=>Node) nodes; - - function findResolver(bytes12 nodeId, bytes32 label) - returns (uint16 rcode, uint32 ttl, bytes12 rnode, address raddress) - { - var subnode = nodes[nodeId].subnodes[label]; - if (subnode.addr == address(0)) { - rcode = RCODE_NXDOMAIN; - return; - } - - ttl = subnode.ttl; - rnode = subnode.nodeId; - raddress = subnode.addr; - } - - function resolve(bytes12 nodeId, bytes32 qtype, uint16 index) - returns (uint16 rcode, bytes16 rtype, uint32 ttl, uint16 len, - bytes32 data) - { - var node = nodes[nodeId]; - if (!node.exists) { - rcode = RCODE_NXDOMAIN; - return; - } - - for(uint i = 0; i < node.records.length; i++) { - var record = node.records[i]; - if (qtype == TYPE_STAR || qtype == record.rtype) { - if (index > 0) { - index--; - continue; - } - - rtype = record.rtype; - ttl = record.ttl; - len = record.len; - data = record.data; - return; - } - } - - // Returns with rcode=RCODE_OK and len=0, indicates record not found. - return; - } -} - -/** - * Authoritative resolver that allows its owner to insert and update records. - */ -contract OwnedRegistrar is Resolver { - address _owner; - uint96 nextNodeId = 0; - - modifier owner_only { if (msg.sender != _owner) throw; _ } - - function OwnedRegistrar() { - _owner = msg.sender; - } - - function setOwner(address owner) owner_only { - _owner = owner; - } - - /** - * @dev Allocates a new node and returns its ID. - * @return nodeId The ID of the newly created (empty) node. - */ - function createNode() owner_only returns (bytes12 nodeId) { - nodeId = bytes12(nextNodeId++); - nodes[nodeId].exists = true; - } - - /** - * @dev Sets a subnode record on the specified node. - * @param nodeId The ID of the node to set a subnode on. - * @param label The label to set the subnode for. - * @param subnodeId The Node ID of the subnode to set. - * @param addr The address of the resolver for this subnode. - * @return An RCODE indicating the status of the operation. - */ - function setSubnode(bytes12 nodeId, bytes32 label, bytes12 subnodeId, - address addr, uint32 ttl) - owner_only returns (uint16 rcode) - { - var node = nodes[nodeId]; - if (!node.exists) - return RCODE_NXDOMAIN; - - node.subnodes[label].nodeId = subnodeId; - node.subnodes[label].addr = addr; - node.subnodes[label].ttl = ttl; - return RCODE_OK; - } - - /** - * @dev Convenience function to create and return a subnode. Equivalent to - * calling `createNode` followed by `setSubnode`. - * @param nodeId The ID of the node to create a subnode on. - * @param label The label to set the subnode for. - * @return An RCODE indicating the status of the operation, and the ID of - * the newly created subnode. - */ - function createSubnode(bytes12 nodeId, bytes32 label, uint32 ttl) - owner_only returns (uint16 rcode, bytes12 subnodeId) - { - subnodeId = createNode(); - rcode = setSubnode(nodeId, label, subnodeId, address(this), ttl); - } - - /** - * @dev Appends a new resource record to the specified node. - * @param nodeId The ID of the node to append an RR to. - * @param rtype The RR type. - * @param ttl The TTL of the provided RR. - * @param len The length of the provided RR. - * @param data The data to append. - * @return RCODE_OK on success, or RCODE_NXDOMAIN if the node does not exist. - */ - function appendRR(bytes12 nodeId, bytes16 rtype, uint32 ttl, uint16 len, - bytes32 data) - owner_only returns (uint16 rcode) - { - var node = nodes[nodeId]; - if (!node.exists) - return RCODE_NXDOMAIN; - - node.records.length += 1; - var record = node.records[node.records.length - 1]; - record.rtype = rtype; - record.ttl = ttl; - record.len = len; - record.data = data; - - return RCODE_OK; - } - - /** - * @dev Deletes the specified resource record. Ordering of remaining records - * is not guaranteed to be preserved unless deleting the last record. - * @param nodeId The ID of the node to delete an RR from. - * @param idx The index of the RR to delete. - * @return RCODE_OK on success, RCODE_NXDOMAIN if the node does not exist, - * RCODE_REFUSED if the index is out of bounds. - */ - function deleteRR(bytes12 nodeId, uint16 idx) - owner_only returns (uint16 rcode) - { - var node = nodes[nodeId]; - if (!node.exists) - return RCODE_NXDOMAIN; - - if (idx >= node.records.length) - return RCODE_REFUSED; - - if (idx != node.records.length - 1) { - node.records[idx] = node.records[node.records.length - 1]; - } - node.records.length--; - - return RCODE_OK; - } -} -``` - -Local Resolver Library ----------------------- -This library code implements a basic local resolver. It supports CNAME resolution, but not extended records or caching. - -``` -import 'github.com/arachnid/solidity-stringutils/StringUtils.sol'; - -contract Resolver { - function findResolver(bytes12 nodeId, bytes32 label) - returns (uint16 rcode, uint32 ttl, bytes12 rnode, address raddress); - function resolve(bytes12 nodeId, bytes32 qtype, uint16 index) - returns (uint16 rcode, bytes16 rtype, uint32 ttl, uint16 len, - bytes32 data); -} - -contract LocalResolver is StringUtils { - // Response codes. - uint8 constant RCODE_OK = 0; - uint8 constant RCODE_NXDOMAIN = 3; - - Resolver private root; - - function LocalResolver(address _root) { - root = Resolver(_root); - } - - function findResolver(string name) - returns (uint16 rcode, Resolver resolver, bytes12 nodeId) - { - resolver = root; - var lastIdx = int(bytes(name).length - 1); - while (lastIdx > 0) { - var idx = strrstr(name, ".", uint(lastIdx)) + 1; - var label = sha3_substring(name, uint(idx), uint(lastIdx - idx) + 1); - uint32 ttl; - address addr; - (rcode, ttl, nodeId, addr) = resolver.findResolver(nodeId, label); - if (rcode != RCODE_OK) - return; - resolver = Resolver(addr); - lastIdx = idx - 2; - } - } - - function resolveOne(string name, bytes16 qtype) - returns (uint16 rcode, bytes16 rtype, uint16 len, bytes32 data) - { - Resolver resolver; - bytes12 nodeId; - (rcode, resolver, nodeId) = findResolver(name); - - uint32 ttl; - (rcode, rtype, ttl, len, data) = resolver.resolve(nodeId, qtype, 0); - } - - /** - * Implements the legacy registrar addr() function. - */ - function addr(string name) returns (address) { - var (rcode, rtype, len, data) = resolveOne(name, "HA"); - return address(data); - } - - /** - * Implements the legacy registrar content() function. - */ - function content(string name) returns (address) { - var (rcode, rtype, len, data) = resolveOne(name, "CHASH"); - return address(data); - } -} -``` diff --git a/README.md b/README.md index 651165ec..9a8119fb 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,52 @@ -# EIP [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/EIPs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -Ethereum Improvement Proposal. EIPs propose and describe changes made to Ethereum Protocol. - -People wishing to submit EIPs first should propose their idea as an issue and then formalize it using a PR. After discussion it will be published here. Having an EIP here does not make it a formally accepted standard until its status becomes Active. For a EIP to become Active requires the mutual consent of the community. An EIP is not finalized until it has been implemented and is in use. Those proposing changes should consider that ultimately consent may rest with the consensus of the Ethereum users. +# EIPs [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/EIPs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +Ethereum Improvement Proposals (EIPs) describe standards for the Ethereum platform, including core protocol specifications, client APIs, and contract standards. # Contributing First review [EIP-1](EIPS/eip-1.md). Then clone the repository and add your EIP to it. There is a [template EIP here](eip-X.md). Then submit a Pull Request to Ethereum's [EIPs repository](https://github.com/ethereum/EIPs). -# Current EIPS -| Number |Title | Author | Type | Layer | Status / Discussion | -| ------------- | ------------ | ------ | ----- | -------------| ------------------- | -| [1](EIPS/eip-1.md) | EIP Purpose and Guidelines | Martin Becze/Hudson Jameson | Meta | | Active | -| [2](EIPS/eip-2.mediawiki) | Homestead Hard-fork Changes | Vitalik Buterin | Standard | homestead (hard-fork) | Accepted | -| [3](EIPS/eip-3.mediawiki) | Addition of CALLDEPTH opcode | Martin Holst Swende | Standard | Consensus (hard-fork) | [Draft](https://github.com/ethereum/EIPs/issues/25) | -| [4](EIPS/eip-4.mediawiki) | EIP Classification | Joseph Chow | Meta | | Draft | -| [5](EIPS/eip-5.md) | Gas Usage for `RETURN` and `CALL*` | Christian Reitwiessner | Standard | Consensus (hard-fork) | [Draft](https://github.com/ethereum/EIPs/issues/8) | -| [6](EIPS/eip-6.md) | Renaming Suicide Variable | Hudson Jameson | Meta | | [Draft](https://github.com/ethereum/EIPs/pull/42) | -| [7](EIPS/eip-7.md) | DELEGATECALL | Vitalik Buterin | Standard | homestead (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/23) | -| [8](EIPS/eip-8.md) | devp2p Forward Compatibility Requirements for Homestead | Felix Lange | Standard | Networking | [Accepted](https://github.com/ethereum/EIPs/pull/49) | -| [150](https://github.com/ethereum/EIPs/issues/150) | Gas cost changes for IO-heavy operations | Vitalik Buterin | Standard | Consensus (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/150) | -| [155](https://github.com/ethereum/EIPs/issues/155) | Simple replay attack protection | Vitalik Buterin | Standard | Consensus (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/155) | -| [160](https://github.com/ethereum/EIPs/issues/160) | EXP cost increase | Vitalik Buterin | Standard | Consensus (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/160) | -| [161](https://github.com/ethereum/EIPs/issues/161) | State trie clearing (invariant-preserving alternative) | Gavin Wood | Standard | Consensus (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/161) | -| [170](https://github.com/ethereum/EIPs/issues/170) | Contract code size limit | Vitalik Buterin | Standard | Consensus (hard-fork) | [Accepted](https://github.com/ethereum/EIPs/issues/170) | +# EIP status terms +* **Draft** - an EIP that is open for consideration +* **Accepted** - an EIP that is planned for immediate adoption, i.e. expected to be included in the next hard fork (for Core/Consensus layer EIPs). +* **Final** - an EIP that has been adopted in a previous hard fork (for Core/Consensus layer EIPs). +* **Deferred** - an EIP that is not being considered for immediate adoption. May be reconsidered in the future for a subsequent hard fork. + +# Deferred EIPs (adoption postponed until the Constantinople Metropolis hard fork) +| Number | Title | Author | Layer | Status | +| -------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------- | -------- | +| [86](https://github.com/ethereum/EIPs/pull/208) | Abstraction of transaction origin and signature | Vitalik Buterin | Core | Deferred | +| [96](https://github.com/ethereum/EIPs/pull/210) | Blockhash refactoring | Vitalik Buterin | Core | Deferred | +| [145](EIPS/eip-145.md) | Bitwise shifting instructions in EVM | Alex Beregszaszi, Paweł Bylica | Core | Deferred | + +# Finalized EIPs (standards that have been adopted) +| Number | Title | Author | Layer | Status | +| -------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------| ---------- | -------- | +| [2](EIPS/eip-2.md) | Homestead Hard-fork Changes | Vitalik Buterin | Core | Final | +| [6](EIPS/eip-6.md) | Renaming Suicide Opcode | Hudson Jameson | Interface | Final | +| [7](EIPS/eip-7.md) | DELEGATECALL | Vitalik Buterin | Core | Final | +| [8](EIPS/eip-8.md) | devp2p Forward Compatibility Requirements for Homestead | Felix Lange | Networking | Final | +| [20](EIPS/eip-20-token-standard.md) | ERC-20 Token Standard | Fabian Vogelsteller, Vitalik Buterin | ERC | Final | +| [55](EIPS/eip-55.md) | ERC-55 Mixed-case checksum address encoding | Vitalik Buterin | Core | Final | +| [100](https://github.com/ethereum/EIPs/issues/100) | Change difficulty adjustment to target mean block time including uncles | Vitalik Buterin | Core | Final | +| [137](EIPS/eip-137.md) | Ethereum Domain Name Service - Specification | Nick Johnson | ERC | Final | +| [140](https://github.com/ethereum/EIPs/pull/206) | REVERT instruction in the Ethereum Virtual Machine | Alex Beregszaszi, Nikolai Mushegian | Core | Final | +| [141](EIPS/eip-141.md) | Designated invalid EVM instruction | Alex Beregszaszi | Core | Final | +| [150](EIPS/eip-150.md) | Gas cost changes for IO-heavy operations | Vitalik Buterin | Core | Final | +| [155](EIPS/eip-155.md) | Simple replay attack protection | Vitalik Buterin | Core | Final | +| [160](EIPS/eip-160.md) | EXP cost increase | Vitalik Buterin | Core | Final | +| [161](EIPS/eip-161.md) | State trie clearing (invariant-preserving alternative) | Gavin Wood | Core | Final | +| [162](EIPS/eip-162.md) | ERC-162 ENS support for reverse resolution of Ethereum addresses | Maurelian, Nick Johnson | ERC | Final | +| [170](EIPS/eip-170.md) | Contract code size limit | Vitalik Buterin | Core | Final | +| [181](EIPS/eip-181.md) | ERC-181 ENS support for reverse resolution of Ethereum addresses | Nick Johnson | ERC | Final | +| [190](EIPS/eip-190.md) | ERC-190 Ethereum Smart Contract Packaging Standard | Merriam, Coulter, Erfurt, Catalano, Matias | ERC | Final | +| [196](https://github.com/ethereum/EIPs/pull/213) | Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128 | Christian Reitwiessner | Core | Final | +| [197](https://github.com/ethereum/EIPs/pull/212) | Precompiled contracts for optimal Ate pairing check on the elliptic curve alt_bn128 | Vitalik Buterin, Christian Reitwiessner | Core | Final | +| [198](https://github.com/ethereum/EIPs/pull/198) | Precompiled contract for bigint modular exponentiation | Vitalik Buterin | Core | Final | +| [211](https://github.com/ethereum/EIPs/pull/211) | New opcodes: RETURNDATASIZE and RETURNDATACOPY | Christian Reitwiessner | Core | Final | +| [214](https://github.com/ethereum/EIPs/pull/214) | New opcode STATICCALL | Vitalik Buterin, Christian Reitwiessner | Core | Final | +| [606](EIPS/eip-606.md) | Hardfork Meta: Homestead | Alex Beregszaszi | Meta | Final | +| [607](EIPS/eip-607.md) | Hardfork Meta: Spurious Dragon | Alex Beregszaszi | Meta | Final | +| [608](EIPS/eip-608.md) | Hardfork Meta: Tangerine Whistle | Alex Beregszaszi | Meta | Final | +| [609](EIPS/eip-609.md) | Hardfork Meta: Byzantium | Alex Beregszaszi | Meta | Final | +| [649](https://github.com/ethereum/EIPs/pull/669) | Metropolis Difficulty Bomb Delay and Block Reward Reduction | Afri Schoedon, Vitalik Buterin | Core | Final | +| [658](https://github.com/ethereum/EIPs/pull/658) | Embedding transaction return data in receipts | Nick Johnson | Core | Final | +| [706](EIPS/eip-706.md) | DEVp2p snappy compression | Péter Szilágyi | Networking | Final | diff --git a/preEIPS/README.md b/preEIPS/README.md deleted file mode 100644 index 6b45da17..00000000 --- a/preEIPS/README.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains the early Proof of Concept iteration. It is incompelete. PoC 2, 7, 8 and 9 are missing. diff --git a/preEIPS/poc1.md b/preEIPS/poc1.md deleted file mode 100644 index 8922ba4b..00000000 --- a/preEIPS/poc1.md +++ /dev/null @@ -1,406 +0,0 @@ -Testnet simplifications: - -1. Difficulty formula - -D(genesisblock) = 2^22 -D(block) = D(block.parent) + D(block.parent) / 1024 * (1 if block.timestamp < block.parent.timestamp + 42 else -1) - - -2. Fees - -All fees are burned - -{ poc-2: -txFee = 100x -x = 100000000000000 = 10^14 -blockReward = 1500000000000000000 = 1.5 * 10^18; -} - -{ poc-3: -stepFee = 1x  -dataFee = 20x -memoryFee = 5x -extroFee = 40x -cryptoFee = 20x -newContractFee = 100x -txFee = 100x -x = 100000000000000 = 10^14 -blockReward = 1500000000000000000 = 1.5 * 10^18; -} - - -3. Premine - -We should all put our ethereum addresses made with the pyethtool.py script at https://github.com/ethereum/website/blob/master/pyethtool/pyethtool.py below: - -Each address gets 2^200 units premined - -{ poc-2: -8a40bfaa73256b60764c1bf40675a99083efb075 (G) -93658b04240e4bd4046fd2d6d417d20f146f4b43 (J) -1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) -80c01a26338f0d905e295fccb71fa9ea849ffa12 (A) -} -{ poc-3: -8a40bfaa73256b60764c1bf40675a99083efb075 (G) -e6716f9544a56c530d868e4bfbacb172315bdead (J) -1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) -1a26338f0d905e295fccb71fa9ea849ffa12aaf4 (A) -} - - -4. PoW - -sha(sha(blockheader_without_nonce) ++ nonce) <= 2^256 / difficulty - -where: -nonce and all outputs from sha are byte arrays of length 32; -++ is the concatenation operator; -<= operands are treated as bytearrays in BE format. - - -5. Uncles - -Nodes should NOT attempt to collect any uncles, although uncles should be included in the reward calculation. - - -6. Block & transactions formats: - -Though RLP is data-agnostic, it does specify a canonical representation for integer quantities. It is big-endian with no leading zero-bytes. Thus for elements than feasibly can be stored as integers, it becomes important to specify whether they should adhere to this canonical representation or be left in some other (perhaps more 'native') format. - -In the case of counts, balances, fees and amounts of wei, the canon-integer form must be used when storing in RLP. We call these INTs. - -In the case of hashes (256-bit or 160-bit), user-visible strings and specialised byte-arrays (e.g. hex-prefix notation from the trie), they should be stored as unformatted byte-array data and not altered into some other form. We call these BINs. - -When interpreting RLP data, clients are required to consider non-canonical INT fields in the same way as otherwise invalid RLP data and dismiss it completely. - -Specifically: - -for the Block header: -[ -    parentHash: BIN, -    unclesHash: BIN, -    coinbase: BIN, -    stateRoot: BIN, -    transactionsHash: BIN, -    difficulty: INT, -    timestamp: INT, -    extraData: BIN, -    nonce: BIN -] - -(note: 'nonce', the last element, refers to a hash here and so is binary) - -for entries in the State trie for normal addresses: -[ -    balance: INT, -    nonce: INT -] - -and for contract addresses: -[ -    balance: INT, -    nonce: INT, -    contractRoot: BIN -] - -(note: 'nonce', the second element, refers to a tx-count here and so is integer) - -for transactions: -[ -    nonce: INT, -    recvAddr: BIN, -    value: INT, -    data: [...], -    v: INT, -    r: INT, -    s: INT -] - -(note: 'nonce', the first element, refers to a tx-count here and so is integer) - -The nonce in the transaction refers to the total amount of transactions send from the address up until that moment in time. Not the total amount (ie. equal to the sender's nonce specified in the address) - -for blocks, there are no immediate data field, but lists: -[ -    blockHeader: [...] -    uncleList: [uncleHash1: BIN, uncleHash2: BIN, ...] -    txList: [...] -] - -Uncle-blocks contain only the uncle's header. - - -8. Block hashes - -When mining a block we use the header of the block without the nonce. This hash is also used during nonce validation [prevHash, uncleHash, coinbase, stateRoot, transactionsHash, difficulty, timestamp, extraData] - -When saving and refering to blocks (e.g. broadcasting, fetching, etc) we use the hash of the entire block ie [header (with nonce), uncle list, tx list] - - -9. Genesis Block - -The header of the genesis block is 8 items, and is specified thus: - -[zeroHash256, sha3(rlp([])), zeroHash160, state_root, sha3(rlp([])), 2**22, 0, "", 42] - -zeroHash256 refers to the parent hash, a 256-bit hash which is all zeroes. -zeroHash160 refers to the coinbase address, a 160-bit hash which is all zeroes. -2^22 refers to the difficulty. -0 refers to the timestamp (the Unix epoch). -"" refers to the extradata. -sha3(rlp([])) values refer to the hashes of the transaction and uncle lists, both empty. - -The SHA-3 hash of the RLP of this block (in its entirety) is: - -ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf - - -10. VM - -When a contract address receives a transaction, a virtual machine is initiated with the contract's state. - -10. a. Terms - -There exists a stack of variable size that stores 256-bit values at each location. (Note: most instructions operate solely on the stack altering its state in some way.) - -S'[i] is the ith item counting down from the top of the pre-stack (i.e. the stack immediately after instruction execution), with the top of the stack corresponding to i == 0. - -S[i] is the ith item counting down from the top of the post-stack (i.e. the stack immediately prior to instruction execution), with the top of the stack corresponding to i == 0. - - -The exists a permanent store addressable by a 256-bit value that stores 256-bit values at each location. - -P'[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero PRIOR to instruction execution. - -P[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero AFTER to instruction execution. - - -The exists a temporary store addressable by a 256-bit value that stores 256-bit values at each location. - -T'[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero PRIOR to instruction execution. - -T[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero AFTER instruction execution. - - -PC' is the program counter PRIOR to instruction execution. - -PC is the program counter AFTER instruction execution. - - -FEE(I, S', P', D) is the fee associated with the execution of instruction I with a machine of stack S', permanent store P' and which has already completed D operations. - -It is defined as F where: - -IF I == SSTORE AND P[ S'[0] ] != 0 AND S'[1] == 0 THEN -    F = S + dataFee - memoryFee -IF I == SSTORE AND P[ S'[0] ] == 0 AND S'[1] != 0 THEN -    F = S + dataFee + memoryFee -IF I == SLOAD -    F = S + dataFee -IF I == EXTRO OR I == BALANCE -    F = S + extroFee -IF I == MKTX -    F = S + txFee -IF I == SHA256 OR I == SHA3 OR I == RIPEMD160 OR I == ECMUL OR I == ECADD -    OR I == ECSIGN OR I == ECRECOVER OR I == ECVALID THEN -    F = S + cryptoFee  - -Where: - -S = D >= 16 ? stepFee : 0 - -Notably, MLOAD and MSTORE have no associated 'memory' cost. SLOAD and SSTORE both have a per-time fee (dataFee). There is also a usage 'fee' (not really a fee as it is all ultimately returned to the contract) that is owed to the contract for all non-zero permanent storage elements. This 'fee', memoryFee, is paid by the contract when a permanent storage address is set to a non-zero value and recovered when that address is set to a zero value. On SUICIDE, all permanent storage is dissolved and so all outstanding memoryFees are recovered. -     -     -B[ A ] is the balance of the address given by A, with A interpreted as an address. - -ADDRESS is the address of the present contract. - - -10. b. Initial Operation - -STEPSDONE := 0 -PC' := 0 -FOR ALL i: T'[i] := 0 -S' is initialised such that its cardinality is zero (i.e. the stack starts empty). -P' must be equal to the value of P when the previous execution halted. - -10. c. General Operation - -The given steps are looped: -1. Execution halts if B[ ADDRESS ] < F( P'[PC'], S', P', STEPSDONE ) -2. B[ ADDRESS ] := B[ ADDRESS ] - F( P'[PC'], S', P', STEPSDONE ) -3. The operation given by P'[PC'] determines PC, P, T, S. -4. PC' := PC; P' := P; T' := T; S' := S; STEPSDONE := STEPSDONE + 1 - -10. d. VM Operations - -Summary line: -: - + - -If PC is not defined explicitly, then it must be assumed PC := PC' + 1. Exceptions are PUSH, JMP and JMPI. - -The cardinality of S (i.e. size of the stack) is altered by A - R between S & S', by adding or removing items as necessary from the front. - -Where: -R: The minimal cardinality of the stack for this instruction to proceed. If this is not achieved then the machine halts with an stack underflow exception. (Note: In some cases of some implementations, this is also the number of values "popped" from the implementation's stack during the course of instruction execution.) -(A - R): The net change in cardinality of the stack over the course of instruction execution. - -FOR ALL i: if S[i] is not defined explicitly, then it must be assumed S[i] := S'[i + R - A] where i + R >= A. -FOR ALL i: if T[i] is not defined explicitly, then it must be assumed T[i] := T'[i]. -FOR ALL i: if P[i] is not defined explicitly, then it must be assumed P[i] := P'[i]. - -The expression (COND ? ONE : ZERO), where COND is an expression and ONE and ZERO are both value placeholders, evaluates to ONE if COND is true, and ZERO if COND is false. This is similar to the C-style ternary operator. - -When a 32-byte machine datum is interpreted as a 160-bit address or hash, the rightwards 20 bytes are taken (i.e. the low-order bytes when interpreting the data as Big-Endian). - -++ is the concatenation operator; all operands are byte arrays (mostly 32-byte arrays here, since that's the size of the VM's data & address types). - -LEFT_BYTES(A, n) returns the array bytes comprising the first (leftmost) n bytes of the 32 byte array A, which can be considered equivalent to a single value in the VM. - -10. e. VM Op-code Set - - • 0x00: STOP -0 +0 - ◦ Halts execution. - • 0x01: ADD -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x02: MUL -2 +1 - ◦ S[0] := S'[0] * S'[1] - • 0x03: SUB -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x04: DIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - • 0x05: SDIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x06: MOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - • 0x07: SMOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x08: EXP -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x09: NEG -1 +1 - ◦ S[0] := -S'[0] - • 0x0a: LT -2 +1 - ◦ S[0] := S'[0] < S'[1] ? 1 : 0 - • 0x0b: LE -2 +1 - ◦ S[0] := S'[0] <= S'[1] ? 1 : 0 - • 0x0c: GT -2 +1 - ◦ S[0] := S'[0] > S'[1] ? 1 : 0 - • 0x0d: GE -2 +1 - ◦ S[0] := S'[0] >= S'[1] ? 1 : 0 - • 0x0e: EQ -2 +1 - ◦ S[0] := S'[0] == S'[1] ? 1 : 0 - • 0x0f: NOT -1 +1 - ◦ S[0] := S'[0] == 0 ? 1 : 0 - • 0x10: MYADDRESS -0 +1 - ◦ S[0] := ADDRESS - • 0x11: TXSENDER -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the sender of the transaction that initiated this instance. - • 0x12: TXVALUE -0 +1 - ◦ S[0] := V - ◦ Where V is the value of the transaction that initiated this instance. - • 0x13: TXDATAN -0 +1 - ◦ S[0] := N - ◦ Where N is the number of data items of the transaction that initiated this instance. - • 0x14: TXDATA -1 +1 - ◦ S[0] := D[ S'[0] ] - ◦ Where D[i] is the ith data item, counting from zero, of the transaction that initiated this instance. - • 0x15: BLK_PREVHASH -0 +1 - ◦ S[0] := H - ◦ Where H is the SHA3 hash of the previous block. - • 0x16: BLK_COINBASE -0 +1 - ◦ S[0] := A - ◦ Where A is the coinbase address of the current block. - • 0x17: BLK_TIMESTAMP -0 +1 - ◦ S[0] := T - ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). - • 0x18: BLK_NUMBER -0 +1 - ◦ S[0] := N - ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). - • 0x19: BLK_DIFFICULTY -0 +1 - ◦ S[0] := D - ◦ Where D is the difficulty of the current block. - • 0x1a: BLK_NONCE -0 +1 - ◦ S[0] := H - ◦ Where H is the none of the previous block. - • 0x1b: BASEFEE -0 +1 - ◦ S[0] := V - ◦ Where V is the value of the current base fee (i.e. the fee multiplier). - •  0x20: SHA256 -(minimum: 1) +1 - ◦ S[0] := SHA256( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where: - ◦ N = FLOOR(S'[0] / 32) - ◦ R = S'[0] % 32 - •  0x21: RIPEMD160 -(minimum: 1) +1 - ◦ S[0] := RIPEMD160( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where all entities are as in SHA256 (0x20), above. - • 0x22: ECMUL -3 +1 - • 0x23: ECADD -4 +1 - • 0x24: ECSIGN -2 +1 - • 0x25: ECRECOVER -4 +1 - • 0x26: ECVALID -2 +1 - • 0x27: SHA3 -(minimum: 1) +1 - ◦ S[0] := SHA3( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where all entities are as in SHA256 (0x20), above. - • 0x30: PUSH X -0 +1 - ◦ PC := PC' + 2 - ◦ S[0] := P[PC' + 1] - • 0x31: POP -1 +0 - • 0x32: DUP -1 +2 - ◦ S[0] := S'[0] - • 0x33: SWAP -2 +2 - ◦ S[0] := S'[1] - ◦ S[1] := S'[0] - • 0x34: MLOAD -1 +1 - ◦ S[0] := T'[ S'[0] ] - • 0x35: MSTORE -2 +0 - ◦ T[ S'[0] ] := S'[1] - • 0x36: SLOAD -1 +1 - ◦ S[0] := P'[ S'[0] ] - • 0x37: SSTORE -2 +0 - ◦ P[ S'[0] ] := S'[1] - • 0x38: JMP -1 +0 - ◦ PC := S'[0] - • 0x39: JMPI -2 +0 - ◦ PC := S'[0] == 0 ? PC' : S'[1] - • 0x3a: IND -0 +1 - ◦ S[0] := PC - • 0x3b: EXTRO -2 +1 - ◦ S[0] := CONTRACT[ S'[0] ].P[ S'[1] ] - ◦ Where CONTRACT[ A ].P is the permanent store of the contract A, with A interpreted as an address. - • 0x3c: BALANCE -1 +1 - ◦ S[0] := B[ S'[0] ] - • 0x3d: MKTX -(minimum: 3) +0 - ◦ Executes a transaction where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The data of the transaction is given by S'[3], S'[4], ... S'[ 2 + S'[2] ] - ◦ (Thus the number of data items of the transaction is given by S'[2].) - • 0x3f: SUICIDE -1 +0 - ◦ Halts execution. - ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee - ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] - ◦ Removes all contract-related information from the Ethereum system. - - -11. VM Memory State - -The memory state of the contract (which forms contractRoot) is formed by a secondary trie which may exist within the same database as the rest of the state. The root of this secondary trie defines the contractRoot. - -Whereas the main state trie has keys of length 160-bit (pertaining to an address in ethereum), the secondary contract state trie has keys of length 256-bit (pertaining to a point in memory of the virtual machine). In both cases, the key is a fixed length number of bytes. Leftly zeroes are not removed. - -Both tries have values encoded as RLP, whereby the value is interpreted as a single RLP element that is a 256-bit binary block (i.e. a 32 byte array). - -11. a. No Zeroes Stored in Trie - -Nodes in the memory trie may have any value EXCEPT zero (which is encoded in RLP as the empty byte array). We are able to do this because we assume that the value of a memory location, if not specified in the trie, defaults to zero. - -If a location in memory ever becomes zero, no value is stored in the trie for that location (requiring the removal of an entry from the trie if the previous value at that location is non-zero). If a memory lookup (i.e. SLOAD) ever happens for an undefined key, then the value returned is zero. - - -12. VM Tests - diff --git a/preEIPS/poc3.md b/preEIPS/poc3.md deleted file mode 100644 index 37901237..00000000 --- a/preEIPS/poc3.md +++ /dev/null @@ -1,424 +0,0 @@ -Testnet simplifications: - -1. Difficulty formula - -D(genesisblock) = 2^22 -D(block) = D(block.parent) + D(block.parent) / 1024 * (1 if block.timestamp < block.parent.timestamp + 42 else -1) - - -2. Fees - -All fees are burned - -{ poc-2: -txFee = 100x -x = 100000000000000 = 10^14 -blockReward = 1500000000000000000 = 1.5 * 10^18; -} - -{ poc-3: -stepFee = 1x  -dataFee = 20x -memoryFee = 5x -extroFee = 40x -cryptoFee = 20x -newContractFee = 100x -txFee = 100x -x = 100000000000000 = 10^14 -blockReward = 1500000000000000000 = 1.5 * 10^18; -} - - -3. Premine - -We should all put our ethereum addresses made with the pyethtool.py script at https://github.com/ethereum/website/blob/master/pyethtool/pyethtool.py below: - -Each address gets 2^200 units premined - -{ poc-2: -8a40bfaa73256b60764c1bf40675a99083efb075 (G) -93658b04240e4bd4046fd2d6d417d20f146f4b43 (J) -1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) -80c01a26338f0d905e295fccb71fa9ea849ffa12 (A) -} -{ poc-3 & above: -8a40bfaa73256b60764c1bf40675a99083efb075 (G) -e6716f9544a56c530d868e4bfbacb172315bdead (J) -1e12515ce3e0f817a4ddef9ca55788a1d66bd2df (V) -1a26338f0d905e295fccb71fa9ea849ffa12aaf4 (A) -} - - -4. PoW - -sha(sha(blockheader_without_nonce) ++ nonce) <= 2^256 / difficulty - -where: -nonce and all outputs from sha are byte arrays of length 32; -++ is the concatenation operator; -<= operands are treated as bytearrays in BE format. - - -5. Uncles - -Nodes should NOT attempt to collect any uncles, although uncles should be included in the reward calculation. - - -6. Block & transactions formats: - -Though RLP is data-agnostic, it does specify a canonical representation for integer quantities. It is big-endian with no leading zero-bytes. Thus for elements than feasibly can be stored as integers, it becomes important to specify whether they should adhere to this canonical representation or be left in some other (perhaps more 'native') format. - -In the case of counts, balances, fees and amounts of wei, the canon-integer form must be used when storing in RLP. We call these INTs. - -In the case of hashes (256-bit or 160-bit), user-visible strings and specialised byte-arrays (e.g. hex-prefix notation from the trie), they should be stored as unformatted byte-array data and not altered into some other form. We call these BINs. - -When interpreting RLP data, clients are required to consider non-canonical INT fields in the same way as otherwise invalid RLP data and dismiss it completely. - -Specifically: - -for the Block header: -[ -    parentHash: BIN, -    unclesHash: BIN, -    coinbase: BIN, -    stateRoot: BIN, -    transactionsHash: BIN, -    difficulty: INT, -    timestamp: INT, -    extraData: BIN, -    nonce: BIN -] - -(note: 'nonce', the last element, refers to a hash here and so is binary) - -for entries in the State trie for normal addresses: -[ -    balance: INT, -    nonce: INT -] - -and for contract addresses: -[ -    balance: INT, -    nonce: INT, -    contractRoot: BIN -] - -(note: 'nonce', the second element, refers to a tx-count here and so is integer) - -for transactions: -[ -    nonce: INT, -    recvAddr: BIN, -    value: INT, -    data:  -    v: INT, -    r: INT, -    s: INT -] - -(note: 'nonce', the first element, refers to a tx-count here and so is integer) - -The nonce in the transaction refers to the total amount of transactions sent from the address up until that moment in time. - -for blocks, there are no immediate data field, but lists: -[ -    blockHeader: [...] -    uncleList: [ [...], [...], ... ] -    txList: [ [...], [...], ... ] -] - -Uncle-blocks contain only the uncle's header. - - -7. Network - -As specified on https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-Wire-Protocol - - -8. Block hashes - -When mining a block we use the header of the block without the nonce. This hash is also used during nonce validation. This header-without-nonce therefore contains [prevHash, uncleHash, coinbase, stateRoot, transactionsHash, difficulty, timestamp, extraData]. - -When saving and refering to blocks (e.g. broadcasting, fetching, etc) we use the hash of the entire block ie [header (with nonce), uncle list, tx list] - - -9. Genesis Block - -The header of the genesis block is 9 items, and is specified thus: - -[zeroHash256, sha3(rlp([])), zeroHash160, state_root, sha3(rlp([])), 2**22, 0, "", 42] - -zeroHash256 refers to the parent hash, a 256-bit hash which is all zeroes. -zeroHash160 refers to the coinbase address, a 160-bit hash which is all zeroes. -2^22 refers to the difficulty. -0 refers to the timestamp (the Unix epoch). -"" refers to the extradata. -sha3(rlp([])) values refer to the hashes of the transaction and uncle lists, both empty. - -The SHA-3 hash of the RLP of this block (in its entirety) is: - -ab6b9a5613970faa771b12d449b2e9bb925ab7a369f0a4b86b286e9d540099cf - - -10. VM - -When a contract address receives a transaction, a virtual machine is initiated with the contract's state. - -10. a. Terms - -There exists a stack of variable size that stores 256-bit values at each location. (Note: most instructions operate solely on the stack altering its state in some way.) - -S'[i] is the ith item counting down from the top of the pre-stack (i.e. the stack immediately after instruction execution), with the top of the stack corresponding to i == 0. - -S[i] is the ith item counting down from the top of the post-stack (i.e. the stack immediately prior to instruction execution), with the top of the stack corresponding to i == 0. - - -The exists a permanent store addressable by a 256-bit value that stores 256-bit values at each location. - -P'[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero PRIOR to instruction execution. - -P[i] is the permanent store (sometimes refered to as 'state' or 'store') of the VM at index i counting from zero AFTER to instruction execution. - - -The exists a temporary store addressable by a 256-bit value that stores 256-bit values at each location. - -T'[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero PRIOR to instruction execution. - -T[i] is the temporary store (sometimes refered to as 'memory') of the VM at index i counting from zero AFTER instruction execution. - - -PC' is the program counter PRIOR to instruction execution. - -PC is the program counter AFTER instruction execution. - - -FEE(I, S', P', D) is the fee associated with the execution of instruction I with a machine of stack S', permanent store P' and which has already completed D operations. - -It is defined as F where: - -IF I == SSTORE AND P[ S'[0] ] != 0 AND S'[1] == 0 THEN -    F = S + dataFee - memoryFee -IF I == SSTORE AND P[ S'[0] ] == 0 AND S'[1] != 0 THEN -    F = S + dataFee + memoryFee -IF I == SLOAD -    F = S + dataFee -IF I == EXTRO OR I == BALANCE -    F = S + extroFee -IF I == MKTX -    F = S + txFee -IF I == SHA256 OR I == SHA3 OR I == RIPEMD160 OR I == ECMUL OR I == ECADD -    OR I == ECSIGN OR I == ECRECOVER OR I == ECVALID THEN -    F = S + cryptoFee  - -Where: - -S = D >= 16 ? stepFee : 0 - -Notably, MLOAD and MSTORE have no associated 'memory' cost. SLOAD and SSTORE both have a per-time fee (dataFee). There is also a usage 'fee' (not really a fee as it is all ultimately returned to the contract) that is owed to the contract for all non-zero permanent storage elements. This 'fee', memoryFee, is paid by the contract when a permanent storage address is set to a non-zero value and recovered when that address is set to a zero value. On SUICIDE, all permanent storage is dissolved and so all outstanding memoryFees are recovered. -     -     -B[ A ] is the balance of the address given by A, with A interpreted as an address. - -ADDRESS is the address of the present contract. - - -10. b. Initial Operation - -STEPSDONE := 0 -PC' := 0 -FOR ALL i: T'[i] := 0 -S' is initialised such that its cardinality is zero (i.e. the stack starts empty). -P' must be equal to the value of P when the previous execution halted. - - -10. c. General Operation - -The given steps are looped: -1. Execution halts if B[ ADDRESS ] < F( P'[PC'], S', P', STEPSDONE ) -2. B[ ADDRESS ] := B[ ADDRESS ] - F( P'[PC'], S', P', STEPSDONE ) -3. The operation given by P'[PC'] determines PC, P, T, S. -4. PC' := PC; P' := P; T' := T; S' := S; STEPSDONE := STEPSDONE + 1 - - -10. d. VM Operations - -Summary line: -: - + - -If PC is not defined explicitly, then it must be assumed PC := PC' + 1. Exceptions are PUSH, JMP and JMPI. - -The cardinality of S (i.e. size of the stack) is altered by A - R between S & S', by adding or removing items as necessary from the front. - -Where: -R: The minimal cardinality of the stack for this instruction to proceed. If this is not achieved then the machine halts with a stack underflow exception. (Note: In some cases of some implementations, this is also the number of values "popped" from the implementation's stack during the course of instruction execution.) -(A - R): The net change in cardinality of the stack over the course of instruction execution. - -FOR ALL i: if S[i] is not defined explicitly, then it must be assumed S[i] := S'[i + R - A] where i + R >= A. -FOR ALL i: if T[i] is not defined explicitly, then it must be assumed T[i] := T'[i]. -FOR ALL i: if P[i] is not defined explicitly, then it must be assumed P[i] := P'[i]. - -The expression (COND ? ONE : ZERO), where COND is an expression and ONE and ZERO are both value placeholders, evaluates to ONE if COND is true, and ZERO if COND is false. This is similar to the C-style ternary operator. - -When a 32-byte machine datum is interpreted as a 160-bit address or hash, the rightwards 20 bytes are taken (i.e. the low-order bytes when interpreting the data as Big-Endian). - -++ is the concatenation operator; all operands are byte arrays (mostly 32-byte arrays here, since that's the size of the VM's data & address types). - -LEFT_BYTES(A, n) returns the array bytes comprising the first (leftmost) n bytes of the 32 byte array A, which can be considered equivalent to a single value in the VM. - -10. e. VM Op-code Set - - • 0x00: STOP -0 +0 - ◦ Halts execution. - • 0x01: ADD -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x02: MUL -2 +1 - ◦ S[0] := S'[0] * S'[1] - • 0x03: SUB -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x04: DIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - • 0x05: SDIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x06: MOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - • 0x07: SMOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x08: EXP -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x09: NEG -1 +1 - ◦ S[0] := -S'[0] - • 0x0a: LT -2 +1 - ◦ S[0] := S'[0] < S'[1] ? 1 : 0 - • 0x0b: LE -2 +1 - ◦ S[0] := S'[0] <= S'[1] ? 1 : 0 - • 0x0c: GT -2 +1 - ◦ S[0] := S'[0] > S'[1] ? 1 : 0 - • 0x0d: GE -2 +1 - ◦ S[0] := S'[0] >= S'[1] ? 1 : 0 - • 0x0e: EQ -2 +1 - ◦ S[0] := S'[0] == S'[1] ? 1 : 0 - • 0x0f: NOT -1 +1 - ◦ S[0] := S'[0] == 0 ? 1 : 0 - • 0x10: MYADDRESS -0 +1 - ◦ S[0] := ADDRESS - • 0x11: TXSENDER -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the sender of the transaction that initiated this instance. - • 0x12: TXVALUE -0 +1 - ◦ S[0] := V - ◦ Where V is the value of the transaction that initiated this instance. - • 0x13: TXDATAN -0 +1 - ◦ S[0] := N - ◦ Where N is the number of data items of the transaction that initiated this instance. - • 0x14: TXDATA -1 +1 - ◦ S[0] := D[ S'[0] ] - ◦ Where D[i] is the ith data item, counting from zero, of the transaction that initiated this instance. - • 0x15: BLK_PREVHASH -0 +1 - ◦ S[0] := H - ◦ Where H is the SHA3 hash of the previous block. - • 0x16: BLK_COINBASE -0 +1 - ◦ S[0] := A - ◦ Where A is the coinbase address of the current block. - • 0x17: BLK_TIMESTAMP -0 +1 - ◦ S[0] := T - ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). - • 0x18: BLK_NUMBER -0 +1 - ◦ S[0] := N - ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). - • 0x19: BLK_DIFFICULTY -0 +1 - ◦ S[0] := D - ◦ Where D is the difficulty of the current block. - • 0x1a: BLK_NONCE -0 +1 - ◦ S[0] := H - ◦ Where H is the none of the previous block. - • 0x1b: BASEFEE -0 +1 - ◦ S[0] := V - ◦ Where V is the value of the current base fee (i.e. the fee multiplier). - •  0x20: SHA256 -(minimum: 1) +1 - ◦ S[0] := SHA256( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where: - ◦ N = FLOOR(S'[0] / 32) - ◦ R = S'[0] % 32 - •  0x21: RIPEMD160 -(minimum: 1) +1 - ◦ S[0] := RIPEMD160( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where all entities are as in SHA256 (0x20), above. - • 0x22: ECMUL -3 +1 - • 0x23: ECADD -4 +1 - • 0x24: ECSIGN -2 +1 - • 0x25: ECRECOVER -4 +1 - • 0x26: ECVALID -2 +1 - • 0x27: SHA3 -(minimum: 1) +1 - ◦ S[0] := SHA3( S'[1] ++ S'[2] ++ ... S'[N] ++ LEFT_BYTES(S'[N], R) ) - ◦ Where all entities are as in SHA256 (0x20), above. - • 0x30: PUSH X -0 +1 - ◦ PC := PC' + 2 - ◦ S[0] := P[PC' + 1] - • 0x31: POP -1 +0 - • 0x32: DUP -1 +2 - ◦ S[0] := S'[0] - • 0x33: SWAP -2 +2 - ◦ S[0] := S'[1] - ◦ S[1] := S'[0] - • 0x34: MLOAD -1 +1 - ◦ S[0] := T'[ S'[0] ] - • 0x35: MSTORE -2 +0 - ◦ T[ S'[0] ] := S'[1] - • 0x36: SLOAD -1 +1 - ◦ S[0] := P'[ S'[0] ] - • 0x37: SSTORE -2 +0 - ◦ P[ S'[0] ] := S'[1] - • 0x38: JMP -1 +0 - ◦ PC := S'[0] - • 0x39: JMPI -2 +0 - ◦ PC := S'[0] == 0 ? PC' : S'[1] - • 0x3a: IND -0 +1 - ◦ S[0] := PC - • 0x3b: EXTRO -2 +1 - ◦ S[0] := CONTRACT[ S'[0] ].P[ S'[1] ] - ◦ Where CONTRACT[ A ].P is the permanent store of the contract A, with A interpreted as an address. - • 0x3c: BALANCE -1 +1 - ◦ S[0] := B[ S'[0] ] - • 0x3d: MKTX -(minimum: 3) +0 - ◦ Immediately executes a transaction where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The data of the transaction is given by S'[3], S'[4], ... S'[ 2 + S'[2] ] - ◦ (Thus the number of data items of the transaction is given by S'[2].) - ◦ NOTE: This transaction is not queued; full ramifications take effect immediately, including balance transfers and any contract invokations. - • 0x3f: SUICIDE -1 +0 - ◦ Halts execution. - ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee - ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] - ◦ Removes all contract-related information from the Ethereum system. - - -11. VM Memory State - -The memory state of the contract (which forms contractRoot) is formed by a secondary trie which may exist within the same database as the rest of the state. The root of this secondary trie defines the contractRoot. - -Whereas the main state trie has keys of length 160-bit (pertaining to an address in ethereum), the secondary contract state trie has keys of length 256-bit (pertaining to a point in memory of the virtual machine). In both cases, the key is a fixed length number of bytes. Leftly zeroes are not removed. - -Both tries have values encoded as RLP, whereby the value is interpreted as a single RLP element that is a 256-bit binary block (i.e. a 32 byte array). - - -11. a. No Zeroes Stored in Trie - -Nodes in the memory trie may have any value EXCEPT zero (which is encoded in RLP as the empty byte array). We are able to do this because we assume that the value of a memory location, if not specified in the trie, defaults to zero. - -If a location in memory ever becomes zero, no value is stored in the trie for that location (requiring the removal of an entry from the trie if the previous value at that location is non-zero). If a memory lookup (i.e. SLOAD) ever happens for an undefined key, then the value returned is zero. - - -12. Transaction Execution - -Transactions should be executed once the validity of the transaction is ascertained. Validity is defined as: - - • Sender address balance at least transaction value + fee. - • Sender address nonce equal to transaction nonce. - • Only when the transaction creates a contract: There is no address collision. - -Once validity is ascertained, the balance may be transfered and the nonce incremented. If the transaction creates a contract then the memory should be initialised according to the transaction data. If the transaction invokes a contract, then that contract should be executed, by restarting an Ethereum Virtual Machine with the contract's state. - - diff --git a/preEIPS/poc4.md b/preEIPS/poc4.md deleted file mode 100644 index 08e8b5d8..00000000 --- a/preEIPS/poc4.md +++ /dev/null @@ -1,679 +0,0 @@ -PoC 4 - -### Big Changes - -We now make a distinction between state and code. Code is stored as an immutable byte array node in the state tree. Accounts have both a state and code hash. When creating contracts, two byte arrays containing EVM code are given: an initialiser (run once then discarded) and the body (stored in the state tree as mentioned). - -Transaction types are distinguished between  - -(i) A message call transaction now contains the following fields: - -    [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] - -(i) b. Whereas a contract creation transaction contains: - -    [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ] (do we need the 0? take it out and it becomes ambiguous with the message call transaction above - How so, there's INIT which takes out the ambiguousity?) - both INIT and DATA are bytearrays hence the ambiguity. - -INIT gets run on creation. If this means that  - -### VM Execution Model - -The current operation is no longer taken from the (256-bit int) storage (P), but instead from a separate immutable byte array of code (C). All operations are bytes, and so are mostly the same as before. The only difference is for PUSH, which must now be split into 32 different opcodes, one for each length of data you wish to push onto the stack. This will mostly be PUSH32 or PUSH1. - -So, given C is the list of bytes of the currently executing code (which, could be CODE or INIT). So the operation to be done is O: - -O = C[ PC' ] - -### Addresses & Words - -Addresses are now formed from words by taking the left 160-bits. Words are formed from addresses conversely, through left-alignment. - -### VM Opcode Set - -# 0s: arithmetic operations - - • 0x00: STOP -0 +0 - ◦ Halts execution. - ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). - • 0x01: ADD -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x02: MUL -2 +1 - ◦ S[0] := S'[0] * S'[1] - • 0x03: SUB -2 +1 - ◦ S[0] := S'[0] - S'[1] - • 0x04: DIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - • 0x05: SDIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x06: MOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - • 0x07: SMOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x08: EXP -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x09: NEG -1 +1 - ◦ S[0] := -S'[0] - • 0x0a: LT -2 +1 - ◦ S[0] := S'[0] < S'[1] ? 1 : 0 - • 0x0b: GT -2 +1 - ◦ S[0] := S'[0] > S'[1] ? 1 : 0 - • 0x0c: EQ -2 +1 - ◦ S[0] := S'[0] == S'[1] ? 1 : 0 - • 0x0d: NOT -1 +1 - ◦ S[0] := S'[0] == 0 ? 1 : 0 - -# 10s: bit operations - - • 0x10: AND -2 +1 - ◦ S[0] := S'[0] AND S'[1] - • 0x11: OR -2 +1 - ◦ S[0] := S'[0] OR S'[1] - • 0x12: XOR -2 +1 - ◦ S[0] := S'[0] XOR S'[1] - • 0x13: BYTE -2 +1 - ◦ S[0] := S'[0]th byte of S'[1] - ▪ if S'[0] < 32 - ◦ S[0] := 0 - ▪ otherwise - ◦ for Xth byte, we count from left - 0th is therefore the leftmost (most significant in BE) byte. - -# 20s: crypto opcodes - - • 0x20: SHA3 -2 +1 - ◦ S[0] := SHA3( T'[ S'[0] ++ ... ++ (S'[0] + S'[1]) ]) - -# 30s: closure state opcodes - - • 0x30: ADDRESS -0 +1 - ◦ S[0] := ADDRESS - ◦ i.e. the address of this closure. - • 0x31: BALANCE -1 +1 - ◦ S[0] := B[ S'[0] ] - ◦ i.e. the balance of this closure. - • 0x32: ORIGIN -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the account that made the original transaction leading to the current closure and is paying the fees - • 0x33: CALLER -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the object that made this call. - • 0x34: CALLVALUE -0 +1 - ◦ S[0] := V - ◦ Where V is the value attached to this call. - • 0x35: CALLDATALOAD -1 +0 - ◦ S[0] := D[ S'[0] ... (S'[0] + 31) ] - ◦ Where D is the data attached to this call (as a byte array). - ◦ Any bytes that are out of bounds of the data are defined as zero. - • 0x36: CALLDATASIZE -0 +1 - ◦ S[0] := DS - ◦ Where DS is the number of bytes of data attached to this call. - • 0x37: GASPRICE -0 +1 - ◦ S[0] := V - ◦ Where V is the current gas price (né fee multiplier). - -# 40s: block operations - - • 0x40: PREVHASH -0 +1 - ◦ S[0] := H - ◦ Where H is the SHA3 hash of the previous block. - • 0x41: COINBASE -0 +1 - ◦ S[0] := A - ◦ Where A is the coinbase address of the current block. - • 0x42: TIMESTAMP -0 +1 - ◦ S[0] := T - ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). - • 0x43: NUMBER -0 +1 - ◦ S[0] := N - ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). - • 0x44: DIFFICULTY -0 +1 - ◦ S[0] := D - ◦ Where D is the difficulty of the current block. - • 0x45: GASLIMIT -0 +1 - ◦ S[0] := L - ◦ Where L is the total gas limit of the current block. Always 10^6. - -# 50s: stack, memory, storage and execution path operations - - • 0x51: POP -1 +0 - • 0x52: DUP -1 +2 - ◦ S[0] := S'[0] - • 0x53: SWAP -2 +2 - ◦ S[0] := S'[1] - ◦ S[1] := S'[0] - • 0x54: MLOAD -1 +1 - ◦ S[0] := T'[ S'[0] ... S'[0] + 31 ] - • 0x55: MSTORE -2 +0 - ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] - • 0x56: MSTORE8 -2 +0 - ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] & 0xff - • 0x57: SLOAD -1 +1 - ◦ S[0] := P'[ S'[0] ] - • 0x58: SSTORE -2 +0 - ◦ P[ S'[0] ] := S'[1] - • 0x59: JUMP -1 +0 - ◦ PC := S'[0] - • 0x5a: JUMPI -2 +0 - ◦ PC := S'[1] == 0 ? PC' : S'[0] - • 0x:5b PC -0 +1 - ◦ S[0] := PC - • 0x5c: MSIZE -0 +1 - ◦ S[0] = sizeof(T) - • 0x5d: GAS - ◦ S[0] := G - ◦ Where G is the amount of gas remaining after executing the opcode. - -# 60s & 70s: push - • 0x60: PUSH1 0 +1 - ◦ S[0] := C[ PC' + 1 ] - ◦ PC := PC' + 2 - • 0x61: PUSH2 0 +1 - ◦ S[0] := C[ PC' + 1 ] ++ C[ PC' + 2 ] - ◦ PC := PC' + 3 -... - • 0x7f: PUSH32 0 +1 - ◦ S[0] := C[ PC' + 1 ] ++ C[ PC' + 2 ] ++ ... ++ C[ PC' + 32 ] - ◦ PC := PC' + 33 - -# f0s: closure-level operations - - • 0xf0: CREATE -5 +1 - ◦ Immediately creates a contract where: - ◦ The endowment is given by S'[0] - ◦ The body code of the eventual closure is given by T'[ S'[1] ... ( S'[1] + S'[2] - 1 ) ] - ◦ The initialisation code of the eventual closure is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] - ◦ (Thus the total number of bytes of the transaction data is given by S'[2] + S'[4].) - ◦ S[0] = A - ◦ where A is the address of the created contract or 0 if the creation failed. - ◦ Fees are deducted from the sender balance to pay for enough gas to complete the operation (i.e. contract creation fee + initial storage fee). If there was not enough gas to complete the operation, then all gas will be deducted and the operation fails. - • 0xf1: CALL -7 +1 - ◦ Immediately executes a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas is given by S'[2] - ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[4].) - ◦ The output data of the call is given by T[ S'[5] ... ( S'[5] + MIN( S'[6], S[0] ) - 1 ) ] - ◦ If 0 gas is specified, transfer all gas from the caller to callee gas balance, otherwise transfer only the amount given. If there isn't enough gas in the caller balance, operation fails. - ◦ If the value is less than the amount in the caller's balance then nothing is executed and the S'[2] gas gets refunded to the caller. - ◦ See Appendix A for execution. - ◦ Add any remaining callee gas to the caller's gas. - ◦ S[0] = R - ◦ where R = 1 when the instrinsic return code of the call is true, R = 0 otherwise. - • NOT YET: POST -5 +1 - ◦ Registers for delayed execution a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas to supply the transaction with is given by S'[2] (paid for from the current gas balance) - ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[4].) - ◦ Contract pays for itself to run at a defered time from its own GAS supply. The miner has no choice but to execute. - • NOT YET: ALARM -6 +1 - ◦ Registers for delayed execution a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas (to convert from ETH at the later time) is given by S'[2] - ◦ The number of blocks to wait before executing is S'[3] - ◦ The input data of the call is given by T'[ S'[4] ... ( S'[4] + S'[5] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[5].) - ◦ Total gas used now is S'[3] * S'[5] * deferFee. - ◦ Contract pays for itself to run at the defered time converting given amount of gas from its ETH balance; if it cannot pay it terminates as a bad transaction. TODO: include baseFee and allow miner freedom to determine whether to execute or not. If not, the next miner will have the chance. - • 0xf2: RETURN -2 +0 - ◦ Halts execution. - ◦ R := T[ S'[0] ... ( S'[0] + S'[1] - 1 ) ] - ◦ Where the output data of the call is specified as R. - ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). - • 0xff: SUICIDE -1 +0 - ◦ Halts execution. - ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee - ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] - ◦ Removes all contract-related information from the Ethereum system. - - - -## Appendix A:  - -CALL has intrinsic parameters: - -TO, VALUE, GAS, INOFFSET, INSIZE, OUTOFFSET, OUTSIZE - -It also finishes an intrinsic boolean value relating to the success of the operation. - -The process for evaluating CALL is as follows: - -1. Let ROLLBACK := S where S is the current state. -2. Let program counter (PC) = 0. -Let it be known that all storage operations operate on TO's state. -Note that the memory is empty, thus (last used index + 1) = 0. -3. Set TXDATA to the first INSIZE bytes of memory starting from INOFFSET in the caller memory. -4. Repeat -    * Calculate the cost of the current instruction (see below), set to C -        * If the instruction is invalid or STOP, goto step 6. -    * If GAS < C then GAS := 0; S := ROLLBACK and evaluation finishes, returning false.  -    * GAS := GAS - C -    * Apply the instruction. -    Until an operation execution error has occured or the instruction is STOP, RETURN or SUICIDE. -5. If the output data of the call (R) is specified (through RETURN), then let the OUTSIZE bytes of caller memory beginning at OUTOFFSET. -6. Returns true. - - -## Appendix B - -Creation of a contract requires than an address be made: this is now defined as the left 160 bits of the SHA3 hash of the RLP encoded structure: - -[ SENDER, NONCE ] - -Should this address already be in use (i.e. have a node in the state tree) then, the address is incremented (as a bigendian int) and retried until it succeeds. - - -## Examples in HLL - -A few new contracts: - -### Namecoin - -    if tx.data[0] > 1000 and !contract.storage[tx.data[0]]: -         contract.storage[tx.data[0]] = tx.data[1] - -### Currency - -    if !contract.storage[1000]: -        contract.storage[1000] = 1 -                contract.storage[tx.sender] = 10^18 -    else: -        fbal = contract.storage[tx.sender] -        tbal = contract.storage[tx.data[0]] -        if fbal >= tx.data[1]: -            contract.storage[tx.sender] = fbal - tx.data[1] -            contract.storage[tx.data[0]] = tbal + tx.data[1] -                 -### Proprietary data feed - -    if tx.sender = : -        contract.storage[tx.data[0]] = tx.data[1] -    else: -        a = bytes(32) -        a[0] = contract.storage[tx.data[0]] -        return(a,32) - -### Stdlib (callable namecoin) - -Idea: [ 0, key, value ] to register, [ 1, key, returnsize, data... ] to use - -        if tx.data[0] == 0: -                if tx.data[1] > 1000 and !contract.storage[tx.data[1]]: -                        contract.storage[tx.data[1]] = tx.data[2] -        else: -                a = bytes(tx.data[2]) -                call(contract.storage[tx.data[1]],tx.value,tx.data+96,tx.datan-96,a,tx.data[2]) -                return(a,tx.data[2]) - -### Compilation tricks - -* Compile `bytes(expr)` as MSIZE DUP < EXPR > 1 SUB 0 PUSH SWAP MSTORE8 -* At the start of every compiled program, if `tx.data` is used more than zero times put `<(n+1)*32> CALLDATA PUSH (n+1) DUP MSTORE` where `n` represents the number of variables in the program (known at compile-time). - - -PoC 4 (was PoC 3.5) - -EVM: - -'Contracts' become 'Closures'. -'Transactions' become the things that are signed in some way and go in the transaction block. A transaction is enacted with a Message Call. -'Message Calls' encode a transfer of value (ETH) and invoke any code associated with the receiving object. - -The original caller (i.e. the original transaction's txsender) pre-pays for a specific amount of 'GAS'. What was baseFee now describes the ETH -> GAS price. Gas is the internal currency of the transaction. Execution operations deplete the GAS supply, as per the original ratios. Once the transaction is finished, any remaining GAS is reconverted back to ETH and refunded. - -Storage remains 256-bit address, 256-bit data. - -Word size: 256-bit (i.e. stack item size 256-bit). - -Memory is byte array (256-bit address, 8-bit data); memoryFee is proportional to greatest index that has ever been referenced in this instance and thus it's highly unlikely addresses will ever go above 32-bit. Whenever a higher memory index is used, the fee difference to take it to the higher usage from the original (lower) usage is charged. MEMSIZE is initially just the size of the input data. Note: MSTORE and MLOAD increase the highest-accessed index to their target index + 31. - -### Big Changes - -NOTE: Crypto functions, except SHA3, removed. -NOTE: SHA3 takes memory location & byte count. - -(i) A transaction now contains the following fields: - -    [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] - -* NONCE is a number, as in PoC-3 -* VALUE is a number, as in PoC-3 -* GAS is (as a number) the amount of GAS that will be exchanged from the sender's ETH balance in order to pay for all costs that happen due to this transaction. -* TO is a number (no longer the fixed 20-byte address that it was in PoC-3) -* GASPRICE is the wei per gas that the sender is willing to pay, as a number. -* DATA is a series of bytes -* V, R, S are numbers as before - -To evaluate: - -Let GASFEE := GAS * GASPRICE - -1. If GAS < TXDATAGAS * len(DATA) + CALLGAS , exit -1. Subtract GASFEE + VALUE from the sender's balance. If the sender's balance is too low, exit. -2. Let G := GAS - (TXDATAGAS * len(DATA) + CALLGAS) -3. Execute CALL operation with the instrinsic parameters (TO, VALUE, G, DATA, sizeof(DATA), 0, 0), (see Appendix A). -4. Add G * GASPRICE to sender's ETH balance where G is the remaining balance of gas from the CALL operation. - -(i) b. If the transaction creates a contract, it must be of the form: - -    [ NONCE, VALUE, GASPRICE, STORAGE, V, R, S ] - -Execution works as follows: 4. The algorithm is relatively computationally quick to verify, although  there is no “nice” verification formula that can be run inside EVM  code. - -Let GASFEE = (SSTOREGAS * D + CREATEGAS) * GASPRICE -where: -D is number of non-zero items of STORAGE - -1. Subtract GASFEE + VALUE from the sender's balance. If the sender's balance is too low, the transaction is declared invalid and no state change is recorded. -2. Put the contract into the blockchain, with the first portion of storage initialised to STORAGE and balance initialised to VALUE. - -NOTE: -(i) To determine if the transaction RLP encodes contract creation, extract nonce/value/basefee and then check if the following (fourth) item is a list - if so it's a creation transaction.     - -(ii) MKTX is renamed CALL. See appendix A for its execution. - -(iii) A new opcode RETURN is added. This allows the caller's memory bounded between OUTOFFSET and OUTOFFSET + OUTSIZE to be specified - -(iv) There is a block size limit (i.e. total gas allowed to be spent per block) which for PoC-3.5 is 10^6. - -### How to define instruction/step cost: - -Constants: - -* STEPGAS = 1 -* SHA3GAS = 20 -* SLOADGAS = 20 -* SSTOREGAS = 100 -* BALANCEGAS = 20 -* CREATEGAS = 100 -* CALLGAS = 20 -* MEMORYGAS = 1 -* TXDATAGAS = 5 [not used in the VM] - -Given an instruction, it is possible to calculate the gas cost of executing it as follows: - -* Unless covered by another rule below, an operation costs < STEPGAS > gas -* SHA3 costs < SHA3GAS > gas -* SLOAD costs < SLOADGAS > gas -* BALANCE costs < BALANCEGAS > gas -* SSTORE costs < D * SSTOREGAS > gas where: -- if the new value of the storage is non-zero and the old is zero, D = 2; -- if the new value of the storage is zero and the old is non-zero, D = 0; -- 1 otherwise. -* CALL costs < CALLGAS + G > gas, where G is the quantity of gas provided; some gas may be refunded though. -* CREATE costs < CREATEGAS + G > gas, where G is the quantity of gas provided. -* When you read or write memory with MSTORE, MLOAD, RETURN, SHA3, CALLDATA or CALL, enlarge the memory so that all bytes now fit in it (memory must always be a whole number of 32-byte words). Suppose that the highest previously accessed memory index is M, and the new index is N. If (N + 31) / 32 > (M + 31) / 32, add an additional < ((N + 31) / 32 - (M + 31) / 32) * MEMORYGAS > gas to the cost. - -For example, if you call `(TO, VALUE, 5000, 512, 512, 1024, 1024)`, and currently `N = 1024`, then we note that the total size of memory required is 2048 (the destination range is [1024, 2047]) and so 1024 addition , so the cost is `CALLGAS + 5000 + 1024 * MEMORYGAS = 6044`. - -### VM Opcode Set - -# 0s: arithmetic operations - - • 0x00: STOP -0 +0 - ◦ Halts execution. - ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). - • 0x01: ADD -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x02: MUL -2 +1 - ◦ S[0] := S'[0] * S'[1] - • 0x03: SUB -2 +1 - ◦ S[0] := S'[0] - S'[1] - • 0x04: DIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - • 0x05: SDIV -2 +1 - ◦ S[0] := S'[0] / S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x06: MOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - • 0x07: SMOD -2 +1 - ◦ S[0] := S'[0] % S'[1] - ◦ S'[0] & S'[1] are interpreted as signed 256-bit values for the purposes of this operation. - • 0x08: EXP -2 +1 - ◦ S[0] := S'[0] + S'[1] - • 0x09: NEG -1 +1 - ◦ S[0] := -S'[0] - • 0x0a: LT -2 +1 - ◦ S[0] := S'[0] < S'[1] ? 1 : 0 - • 0x0b: GT -2 +1 - ◦ S[0] := S'[0] > S'[1] ? 1 : 0 - • 0x0c: EQ -2 +1 - ◦ S[0] := S'[0] == S'[1] ? 1 : 0 - • 0x0d: NOT -1 +1 - ◦ S[0] := S'[0] == 0 ? 1 : 0 - -# 10s: bit operations - - • 0x10: AND -2 +1 - ◦ S[0] := S'[0] AND S'[1] - • 0x11: OR -2 +1 - ◦ S[0] := S'[0] OR S'[1] - • 0x12: XOR -2 +1 - ◦ S[0] := S'[0] XOR S'[1] - • 0x13: BYTE -2 +1 - ◦ S[0] := S'[0]th byte of S'[1] - ▪ if S'[0] < 32 - ◦ S[0] := 0 - ▪ otherwise - ◦ for Xth byte, we count from left - 0th is therefore the leftmost (most significant in BE) byte. - -# 20s: crypto opcodes - - • 0x20: SHA3 -2 +1 - ◦ S[0] := SHA3( T'[ S'[0] ++ ... ++ (S'[0] + S'[1]) ]) - -# 30s: closure state opcodes - - • 0x30: ADDRESS -0 +1 - ◦ S[0] := ADDRESS - ◦ i.e. the address of this closure. - • 0x31: BALANCE -1 +1 - ◦ S[0] := B[ S'[0] ] - ◦ i.e. the balance of this closure. - • 0x32: ORIGIN -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the account that made the original transaction leading to the current closure and is paying the fees - • 0x33: CALLER -0 +1 - ◦ S[0] := A - ◦ Where A is the address of the object that made this call. - • 0x34: CALLVALUE -0 +1 - ◦ S[0] := V - ◦ Where V is the value attached to this call. - • 0x35: CALLDATALOAD -1 +0 - ◦ S[0] := D[ S'[0] ... (S'[0] + 31) ] - ◦ Where D is the data attached to this call (as a byte array). - ◦ Any bytes that are out of bounds of the data are defined as zero. - • 0x36: CALLDATASIZE -0 +1 - ◦ S[0] := DS - ◦ Where DS is the number of bytes of data attached to this call. - • 0x37: GASPRICE -0 +1 - ◦ S[0] := V - ◦ Where V is the current gas price (né fee multiplier). - -# 40s: block operations - - • 0x40: PREVHASH -0 +1 - ◦ S[0] := H - ◦ Where H is the SHA3 hash of the previous block. - • 0x41: COINBASE -0 +1 - ◦ S[0] := A - ◦ Where A is the coinbase address of the current block. - • 0x42: TIMESTAMP -0 +1 - ◦ S[0] := T - ◦ Where T is the timestamp of the current block (given as the Unix time_t when this block began its existence). - • 0x43: NUMBER -0 +1 - ◦ S[0] := N - ◦ Where N is the block number of the current block (counting upwards from genesis block which has N == 0). - • 0x44: DIFFICULTY -0 +1 - ◦ S[0] := D - ◦ Where D is the difficulty of the current block. - • 0x45: GASLIMIT -0 +1 - ◦ S[0] := L - ◦ Where L is the total gas limit of the current block. Always 10^6. - -# 50s: stack, memory, storage and execution path operations - - • 0x50: PUSH X -0 +1 - ◦ PC := PC' + 2 - ◦ S[0] := P[PC' + 1] - • 0x51: POP -1 +0 - • 0x52: I -1 +2 - ◦ S[0] := S'[0] - • 0x53: SWAP -2 +2 - ◦ S[0] := S'[1] - ◦ S[1] := S'[0] - • 0x54: MLOAD -1 +1 - ◦ S[0] := T'[ S'[0] ... S'[0] + 31 ] - • 0x55: MSTORE -2 +0 - ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] - • 0x56: MSTORE8 -2 +0 - ◦ T[ S'[0] ... S'[0] + 31 ] := S'[1] & 0xff - • 0x57: SLOAD -1 +1 - ◦ S[0] := P'[ S'[0] ] - • 0x58: SSTORE -2 +0 - ◦ P[ S'[0] ] := S'[1] - • 0x59: JUMP -1 +0 - ◦ PC := S'[0] - • 0x5a: JUMPI -2 +0 - ◦ PC := S'[1] == 0 ? PC' : S'[0] - • 0x:5b PC -0 +1 - ◦ S[0] := PC - • 0x5c: MSIZE -0 +1 - ◦ S[0] = sizeof(T) - • 0x5d: GAS - ◦ S[0] := G - ◦ Where G is the amount of gas remaining after executing the opcode. - -# 60s: closure-level operations - - • 0x60: CREATE -5 +1 - ◦ Immediately creates a contract where: - ◦ The endowment is given by S'[0] - ◦ The input data of the call is given by T'[ S'[1] ... ( S'[1] + S'[2] - 1 ) ] - ◦ (Thus the number of bytes of the transaction data is given by S'[2].) - ◦ S[0] = A - ◦ where A is the address of the created contract. - ◦ Fees are deducted from the sender balance to pay for enough gas to complete the operation (i.e. contract creation fee + initial storage fee). - • 0x61: CALL -7 +1 - ◦ Immediately executes a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas is given by S'[2] - ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[4].) - ◦ The output data of the call is given by T[ S'[5] ... ( S'[5] + MIN( S'[6], S[0] ) - 1 ) ] - ◦ If 0 gas is specified, transfer all gas from the caller to callee gas balance, otherwise transfer only the amount given. If there isn't enough gas in the caller balance, operation fails. - ◦ If the value is less than the amount in the caller's balance then nothing is executed and the S'[2] gas gets refunded to the caller. - ◦ See Appendix A for execution. - ◦ Add any remaining callee gas to the caller's gas. - ◦ S[0] = R - ◦ where R = 1 when the instrinsic return code of the call is true, R = 0 otherwise. - • NOT YET: POST -5 +1 - ◦ Registers for delayed execution a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas to supply the transaction with is given by S'[2] (paid for from the current gas balance) - ◦ The input data of the call is given by T'[ S'[3] ... ( S'[3] + S'[4] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[4].) - ◦ Contract pays for itself to run at a defered time from its own GAS supply. The miner has no choice but to execute. - • NOT YET: ALARM -6 +1 - ◦ Registers for delayed execution a call where: - ◦ The recipient is given by S'[0], when interpreted as an address. - ◦ The value is given by S'[1] - ◦ The gas (to convert from ETH at the later time) is given by S'[2] - ◦ The number of blocks to wait before executing is S'[3] - ◦ The input data of the call is given by T'[ S'[4] ... ( S'[4] + S'[5] - 1 ) ] - ◦ (Thus the number of bytes of the transaction is given by S'[5].) - ◦ Total gas used now is S'[3] * S'[5] * deferFee. - ◦ Contract pays for itself to run at the defered time converting given amount of gas from its ETH balance; if it cannot pay it terminates as a bad transaction. TODO: include baseFee and allow miner freedom to determine whether to execute or not. If not, the next miner will have the chance. - • 0x62: RETURN -2 +0 - ◦ Halts execution. - ◦ R := T[ S'[0] ... ( S'[0] + S'[1] - 1 ) ] - ◦ Where the output data of the call is specified as R. - ◦ Any gas left over gets returned to caller (or in the case of the top-level call, the sender converted back to ETH). - • 0x7f: SUICIDE -1 +0 - ◦ Halts execution. - ◦ FOR ALL i: IF P[i] NOT EQUAL TO 0 THEN B[ S'[0] ] := B[ S'[0] ] + memoryFee - ◦ B[ S'[0] ] := B[ S'[0] ] + B[ ADDRESS ] - ◦ Removes all contract-related information from the Ethereum system. - -## Appendix A:  - -CALL has intrinsic parameters: - -TO, VALUE, GAS, INOFFSET, INSIZE, OUTOFFSET, OUTSIZE - -It also finishes an intrinsic boolean value relating to the success of the operation. - -The process for evaluating CALL is as follows: - -1. Let ROLLBACK := S where S is the current state. -2. Let program counter (PC) = 0. -Let it be known that all storage operations operate on TO's state. -Note that the memory is empty, thus (last used index + 1) = 0. -3. Set TXDATA to the first INSIZE bytes of memory starting from INOFFSET in the caller memory. -4. Repeat -    * Calculate the cost of the current instruction (see below), set to C -        * If the instruction is invalid or STOP, goto step 6. -    * If GAS < C then GAS := 0; S := ROLLBACK and evaluation finishes, returning false.  -    * GAS := GAS - C -    * Apply the instruction. -    Until an operation execution error has occured or the instruction is STOP, RETURN or SUICIDE. -5. If the output data of the call (R) is specified (through RETURN), then let the OUTSIZE bytes of caller memory beginning at OUTOFFSET. -6. Returns true. - - -## Appendix B - -Creation of a contract is as before, except that should there be an address collision in the creation of contract, the address is incremented (as a bigendian int) and retried until it succeeds. - - -## Examples in HLL - -A few new contracts: - -### Namecoin - -    if tx.data[0] > 1000 and !contract.storage[tx.data[0]]: -         contract.storage[tx.data[0]] = tx.data[1] - -### Currency - -    if !contract.storage[1000]: -        contract.storage[1000] = 1 -                contract.storage[tx.sender] = 10^18 -    else: -        fbal = contract.storage[tx.sender] -        tbal = contract.storage[tx.data[0]] -        if fbal >= tx.data[1]: -            contract.storage[tx.sender] = fbal - tx.data[1] -            contract.storage[tx.data[0]] = tbal + tx.data[1] -                 -### Proprietary data feed - -    if tx.sender = : -        contract.storage[tx.data[0]] = tx.data[1] -    else: -        a = bytes(32) -        a[0] = contract.storage[tx.data[0]] -        return(a,32) - -### Stdlib (callable namecoin) - -Idea: [ 0, key, value ] to register, [ 1, key, returnsize, data... ] to use - -        if tx.data[0] == 0: -                if tx.data[1] > 1000 and !contract.storage[tx.data[1]]: -                        contract.storage[tx.data[1]] = tx.data[2] -        else: -                a = bytes(tx.data[2]) -                call(contract.storage[tx.data[1]],tx.value,tx.data+96,tx.datan-96,a,tx.data[2]) -                return(a,tx.data[2]) - -### Compilation tricks - -* Compile `bytes(expr)` as MSIZE DUP < EXPR > 1 SUB 0 PUSH SWAP MSTORE8 -* At the start of every compiled program, if `tx.data` is used more than zero times put `<(n+1)*32> CALLDATA PUSH (n+1) DUP MSTORE` where `n` represents the number of variables in the program (known at compile-time). \ No newline at end of file diff --git a/preEIPS/poc5.md b/preEIPS/poc5.md deleted file mode 100644 index d6f558be..00000000 --- a/preEIPS/poc5.md +++ /dev/null @@ -1,125 +0,0 @@ -ALTERATIONS FOR SUICIDE - -Suicide's semantics are now: - -All funds are immediately transferred to the nominated recipient account, but the account itself remains valid. It is tagged for destruction, to be completed simultaneously with all remaining gas being refunded to the origination account (this can safely happen simultaneously since the suicidal account is necessarily a contract account and the transaction originator is necessarily externally controlled, non-contract account). - - - - -All accounts become the same type; code/storage is just empty for the non-contract accounts. - -Contract creation just specifies an initialiser; return of initialiser is body. - -[ nonce, price, gas, to, value, data, v, r, s] (to is 0 for contract creation) - -CALLDATACOPY instruction: -CALLDATACOPY MEMINDEX CALLDATAINDEX LEN? -CODESIZE -CODECOPY MEMINDEX CODEINDEX LEN - -CALL is now [ gas, to, value, datain, datain_sz, dataout, dataout_sz ] -CREATE is now [ value, datain, datain_sz ] - -Section 0x30 is now: -        ADDRESS, -        BALANCE, -        ORIGIN, -        CALLER, -        CALLVALUE, -        CALLDATALOAD, -        CALLDATASIZE, -        CALLDATACOPY = 0x37, -        CODESIZE = 0x38, -        CODECOPY = 0x39, -        GASPRICE = 0x3a, - - -Section 0x00 is now: -        STOP = 0x00,                ///< halts execution -        ADD, -        MUL, -        SUB, -        DIV, -        SDIV, -        MOD, -        SMOD, -        EXP, -        NEG, -        LT, -        GT, -        SLT = 0x0c,    // signed less than -        SGT = 0x0d,    // signed greater than -        EQ = 0x0e, -        NOT, - - - - -Use actual formula (LTMA) for gas limit: -gasLimit = floor((parent.gasLimit * (EMAFACTOR - 1) + floor(parent.gasUsed * BLK_LIMIT_FACTOR_NUM / BLK_LIMIT_FACTOR_DEN)) / EMA_FACTOR) - -BLK_LIMIT_FACTOR_NUM = 6 -BLK_LIMIT_FACTOR_DEN = 5 -EMA_FACTOR = 1024 - -For network protocol, switch IP Address to a 4-byte byte-array rather than a list of numbers.  - -Block format is now: -[ header, [ [tx0, s0, g0], [tx1, s1, g1], ...], [u0, u1, u2, ...] ] - -Block header format: -[prevHash, unclesHash, coinbase, stateRoot, txsTrieRoot, difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp, extraData, nonce] - -extraData is a byte array length <= 1024. - -minGasPrice can default to 10 szabo for now. - -use triehash for the txlist instead of sha3ing the RLP: -triehash = Trie("").update(0, [tx0, s0, g0]).update(1, [tx1, s1, g1]).update( ..... ).root - -Where [tx(i), s(i), g(i)] are the ith transaction, the state root after applying the ith transaction, and the gas after applying the ith transaction and 0,1, etc are just numbers - -GAS costs: -Remove gas burn for tx data -5 GAS per byte of TXDATA -500 GAS per TXCOST -TXs no longer pay CREATE/CALL. - - -Genesis block - -Genesis block is: ( B32(0, 0, ...), B32(sha3(B())), B20(0, 0, ...), B32(stateRoot), B32(0, 0, ...), P(2^22), P(0), P(0), P(1000000), P(0), P(0), B(), B32(sha3(B(42))), B(), B() ) - -Genesis block items (as hex) are: -parentHash: 00000000000000000000000000000000000000000000000000000000000000000 -unclesHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 -coinbase: 0000000000000000000000000000000000000000 -stateRoot: 11cc4aaa3b2f97cd6c858fcc0903b9b34b071e1798c91645f0e05e267028cb4a -txsTrieRoot: <> -difficulty: 400000 -number: <> -mixGasPrice: <> -gasLimit: 0f4240 -gasUsed: <> -timestamp: <> -extraData: <> -nonce: 04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829 -transaction: <> -uncles: <> - -Genesis block RLP encoded (as hex) is: -f8abf8a7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a011cc4aaa3b2f97cd6c858fcc0903b9b34b071e1798c91645f0e05e267028cb4aa1680834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0 - -Note: B32 specifies a byte array of length 32, B20 specifies a byte array of length 20, B32(0, 0, ...) specifies a byte array filled with zeroes, B() specifies an empty byte array, B(42) specified a byte array of length 1 whose only element is of vaue 42, P specifies a positive integer (to be encoded as a bytearray in bigendian with no leading zeroes). - - -Javascript Bindings - -async & sync - -async is getX(..., function() {}) -sync is X(...) - - - diff --git a/preEIPS/poc6.md b/preEIPS/poc6.md deleted file mode 100644 index 900546ce..00000000 --- a/preEIPS/poc6.md +++ /dev/null @@ -1,92 +0,0 @@ -POC-7 https://ethereum.etherpad.mozilla.org/14? -Latest changes: - - ---------------------------------------------------- - -Stateless contracts: -Additional opcode: 0xf4: CALLSTATELESS -Calls self, but grabbing the code from the TO argument instead of from one's own address -DONE PY,C++, go/Java - --------------------------------------------------------- - -0x3b EXTCODESIZE -0x3c EXTCODECOPY -like CODECOPY, CODESIZE but takes an additional parameter at beginning (top of stack) containing address from which to copy. -DONE C++, Go, Java,JS - --------------------------------------------------------- - -* zero-size memory reads/writes do not lead to a size increase for fee purposes - -DONE PY,C++, go, Java,JS - --------------------------------------------------------- - -New opcodes: - -0x80...8f: DUP1 ... DUP16 -0x90...9f: SWAP1...SWAP16 (for LLVM cross-compilation) -0x14: ADDMOD -0x15: MULMOD (to make ecrecover easier) - -0x51, 0x52 are INVALID. - -DONE C++/GO/PY/Java,JS - --------------------------------------------------------- - -0xf3: POST (same as call, except 5 arguments in and 0 arguments out, and instead of immediately calling it adds the call to a postqueue, to be executed after everything else (including prior-created posts) within the scope of that transaction execution is executed) - -Transaction finalisation: -- Create contract if transaction was contract-creation -- Keep executing earliest POST while postqueue isn't empty. -- Refund unused gas to caller (this includes gas unused from POSTs) & give fees to miner. -- Execute SUICIDEs. - -DONE C++/GO/PY,JS - ----------------------------------------------------- - -New GHOST protocol - - • A block can contain as uncles headers which satisfy all of the following criteria: - ◦ They are valid headers (not necessarily valid blocks) - ◦ Their parent is a kth generation ancestor for k in {2, 3, 4, 5, 6, 7} - ◦ They were not uncles of the kth generation ancestor for k in {1, 2, 3, 4, 5, 6} - • The uncle reward is increased to 15/16x the main block reward - • The nephew reward (ie. reward for including an uncle) is set to 1/32x the main block reward - • The target block time is 12s (ie. s/42/9/g in the diff adjustment algo) - • >= 5 -> increase - • <= 4 -> reduce - -SUGGESTION: target block time 4s (eg. >= 3 increase <= 2 reduce) as a temporary stress test - -DONE C++/PY/node.js, go/Java - ----------------------------------------------------- - -for blocks, block.hash = sha3(rlp.encode(block.header)) - -for accounts which don't have code, the code is "" -and the codehash is "" (instead of sha3(()) as in PoC5) - -for contract-creation transactions, address is empty rather than 000000000000000... - -DONE C++/PY, go/Java/node.js - ---------------------------------------------------- - -CALL, CREATE, CALLDATACOPY, etc should take memory indices as given, and not as mod 2^64 (this could just be implemented as a <=2^64 error check in the code, since using 2^64 memory will be prohibitively expensive) - -DONE C++/PY, Go/Java - ---------------------------------------------------- - -PoC-6 Networking (parallel downloads) - -DONE C++, Go, node.js/Java - ---------------------------------------------------- -