In the past couple of weeks, my lead C++ developer, Gavin Wood, and I have spent a lot of time meeting with the local Ethereum community in San Francisco and Silicon Valley. We were very excited to see so much interest in our project, and the fact that after just two months we had a meetup group that gets together every week, just like a Bitcoin meetup, with over thirty people attending each time. People in the community are taking it upon themselves to create educational videos, organize events, and experiment with contracts, and one person has independently started writing an Ethereum application in Node.js. However, at the same time, we had the opportunity to take another look at Ethereum’s protocols, see where things are still not ideal, and agree on a large set of changes that will be incorporated, likely with minimal modification, into PoC 3.5 clients.
Transactions as closing
In ES1 and ES2, the MKTX opcode, which allowed contracts to send transactions that triggered other contracts, had one very unintuitive feature: although one would normally expect MKTX to be like a function call, processing the entire transaction at once Then continue the rest of the code, actually MKTX didn’t work that way. Instead, the execution of the call is delayed towards the end – when MKTX is called, a new transaction will be pushed to the front of the block’s transaction stack, and when the execution of the first transaction terminates the execution of the second begins. For example, here’s something you might expect to work:
x = matrix() x[0] = “George” S[1] =MyPUBKEY
mktx(NAMECOIN,10^20,x,2)
if Contract.storage(NAMECOIN)[“george”] == MYPUBKEY: registration_successful = 1 else: registration_successful = 0
//Do more things…
Use the namecoin contract to attempt to register “george”, then use the launch code EXTRO to see if the registration was successful. Looks like this should work. However, of course, this does not happen.
In EVM3 (no longer ES3), we fixed this issue. We do this by taking an idea from ES2 – creating a concept of reusable code, functions, and software libraries, and an idea from ES1 – keeping it simple by keeping code as a sequential set of instructions in state, and combining the two together in the concept of “message calls”. A message call is an operation executed from within a contract that takes a destination address, ether value, and some data as input and calls the contract with that value and data, but also, unlike a transaction, returns the data as output. Therefore, there is also a new RETURN opcode that allows nodes to be executed to return data.
With this system, contracts can now become more robust. Contracts of the traditional type, which perform certain data when receiving message calls, still exist. But now, two other design styles are also possible. First, one can now create a private data feed contract; For example, Bloomberg could publish a contract into which it pays out various asset prices and other market data, and embed in its contract an application programming interface (API) that returns internal data as long as the incoming message call sends at least 1 VIN with it. The fees can’t get much higher; Otherwise, contracts that fetch data from Bloomberg nodes once per block and then provide cheaper transit will be profitable. However, even with a fee worth a quarter of the transaction fee, such a data-feeding business may eventually become very viable. The EXTRO opcode is removed to facilitate this functionality, e.g. The contracts are now opaque from within the system, although it is clear that from the outside one can simply look at Merkel’s tree.
Second, it is possible to create contracts that represent functions; For example, one could have a SHA256 contract or an ECMUL contract to compute those respective functions. There’s one problem with this: twenty bytes to store the address for a particular function call might be a bit much. However, this problem can be solved by creating a single “stdlib” contract containing a few hundred clauses for shared functionality, and contracts can store the address of this contract once as a variable and then access it multiple times simply as “x” (technically, “push 0 mlwad”). This is EVM3’s way of incorporating another key idea from ES2, which is the concept of standard libraries.
Ether and gas
Another important change is that contracts no longer pay for the execution of a contract, but rather transactions do. When you submit a transaction, you must now include BASEFEE and the maximum number of steps you wish to pay for. At the beginning of the transaction execution, BASEFEE multiplied by the maximum steps is immediately deducted from your balance. A new counter is then created, called GAS, which starts with the number of steps you have left. Then the transaction execution begins as before. Each move costs 1 gas, and execution continues until it stops naturally, at which point all remaining gas hits are returned to the sender, or the execution runs out of gas; In this case, all executions are undone but the fee is still paid in full.
This approach has two important benefits. First, it allows miners to know in advance the maximum amount of gas a transaction will consume. Second, and much more importantly, it allows contract writers to spend much less time focusing on making the contract “defensible” against bogus transactions that try to subvert the contract by forcing them to pay fees. For example, consider the old 5-line Namecoin:
if tx.value < block.basefee * 200: stop if !contract.storage[tx.data[0]]or tx.data[0] = 100: contract.storage[tx.data[0]]= tx.data[1]
Two lines, no checks. easier. Focus on the logic, not the details of the protocol. The main weakness of this approach is that it means that if you send a transaction to a contract, you will need to pre-calculate how long it will take to execute (or at least set a reasonable upper limit you are willing to pay), and the contract has the potential to enter an infinite loop. , using all the fuel, and forcing you to pay the toll without any effect. However, it can be said that this is not a problem; When you send a transaction to someone, you’re already implicitly trusting them not to throw money into a ditch (or at least not to complain if they do), and it’s up to the contract to be reasonable. Contracts may also choose to include a reference indicating how much gas you expect to need (I hereby nominate “PUSH 4 JMP” to the implementation code as a voluntary standard)
There is an important extension of this idea, which applies to the concept of message calls: when a contract makes a message call, the contract also determines how much gas the contract on the other end of the call should use. As at the top level, the receiving contract can either finish execution in time or may run out of gas, at which point execution returns to the start of the call but gas is still consumed. Alternatively, contracts could put a zero on the gas fields; In this case, they trust the subcontract with all the remaining gas. The main reason this is necessary is to allow automated contracts and human-controlled contracts to interact with each other; If only the option to contract for all remaining gas was available, automated contracts would not be able to use any human-controlled contracts without absolute trust in their owners. This would make m-of-n data feed applications essentially infeasible. On the other hand, this represents a weakness as the execution engine would need to include the ability to go back to some previous point (specifically, the start of the message call).
New terminology guide
With all the new concepts we’ve introduced, we’ve standardized some of the new terms we’ll be using; We hope this helps clarify the discussion on different topics.
- External actor: A person or other entity capable of interacting with an Ethereum node, but outside the Ethereum world. It can interact with Ethereum by depositing signed transactions and examining the block chain and its associated state. Has one (or more) core accounts.
- Title: A 160-bit code used to identify accounts.
- account: Accounts contain an intrinsic balance and the number of transactions that are kept as part of the Ethereum state. It is owned either by external actors or intrinsically (as an identity) an independent object within Ethereum. If an account selects an independent object, Ethereum will also maintain a storage state specific to that account. Each account has one address that identifies it.
- practical: A piece of data signed by a third party. It represents either a message or a new independent object. Transactions are recorded in each block of the blockchain.
- Independent object: A virtual object that exists only within the virtual state of Ethereum. It has a substantive address. It is only integrated as a virtual machine storage component state.
- Storage condition: Information about a particular autonomous object that is maintained between its runs.
- message: Data (as a set of bytes) and value (specified as Ether) that is passed between two accounts in a completely reliable manner, either through the deterministic operation of an independent object or the cryptographically secure signature of the transaction.
- Message call: The process of passing a message from one account to another. If the destination account is a standalone object, the VM will run with the state of said object and the message will be handled. If the sender of the message is a standalone object, the call will pass any data returned from the VM process.
- Gas: Basic network cost unit. It is paid for exclusively by ether (as of PoC-3.5), which is freely converted to and from gas as needed. There is no gas outside of the internal Ethereum computation engine; Its price is determined by the transaction and miners are free to ignore transactions where the gas price is too low.
Long term offer
We will soon be releasing a full official specification for the above changes, including a new version of the whitepaper that takes into account all of these modifications, as well as a new version of the client that implements them. Later, more changes will likely be made to the EVM, but ETH-HLL will be changed as little as possible; Therefore, it is completely safe to write contracts in ETH-HLL now and they will continue to work even if the language changes.
We still don’t have a final idea of how we will handle mandatory fees; The current approach to stop the gap is to set a block cap of 1,000,000 operations (i.e. gas spending) per block. In economic terms, the mandatory fee and the mandatory block limit are essentially equal; However, the block limit is somewhat more general and theoretically allows a limited number of transactions to enter for free. There will be a blog post covering our latest thoughts on the fees issue soon. Another idea I had, stack traces, can also be implemented later.
In the long term, and perhaps even after Ethereum 1.0, perhaps the holy grail is to attack the last two “core” parts of the system, and see if we can also turn them into contracts: Ether and ECDSA. In such a system, ether would still be the token currency in the system; The current thinking is that we will insert the ether contract at index “1” so that it takes nineteen bytes less to use. However, the execution engine will become much simpler because there will be no concept of currency – instead, it will be all about contracts and message calls. Another interesting benefit is that this would allow the separation of ether and ECDSA, optionally making ether quantum resistant; If you want, you can create an Ether account using NTRU or Lamport nodes instead. However, the disadvantage is that Proof of Stake will not be possible without a protocol-level core currency; This may be a good reason not to go in this direction.



















.jpg)


