Skip to content

Commit

Permalink
Merge pull request ethereum#13759 from ethereum/prevrandao
Browse files Browse the repository at this point in the history
Add `block.prevrandao` as alias for `block.difficulty`
  • Loading branch information
ekpyron authored Jan 25, 2023
2 parents d70d79a + ef6ff2f commit fd9ac9a
Show file tree
Hide file tree
Showing 114 changed files with 842 additions and 221 deletions.
4 changes: 3 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ Language Features:
Compiler Features:
* Commandline Interface: Return exit code ``2`` on uncaught exceptions.
* Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode.
* EVM: Basic support for the EVM version "Paris".
* EVM: Deprecate ``block.difficulty`` and disallow ``difficulty()`` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399).
* EVM: Introduce ``block.prevrandao`` in Solidity and ``prevrandao()`` in inline assembly for EVM versions >= paris.
* EVM: Support for the EVM version "Paris".
* Natspec: Add event Natspec inheritance for devdoc.
* Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode.
* Yul EVM Code Transform: Generate more optimal code for user-defined functions that always terminate a transaction. No return labels will be pushed for calls to functions that always terminate.
Expand Down
5 changes: 3 additions & 2 deletions docs/cheatsheet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Order of Precedence of Operators
================================
.. include:: types/operator-precedence-table.rst

.. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send
.. index:: assert, block, coinbase, difficulty, prevrandao, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send

Global Variables
================
Expand All @@ -32,9 +32,10 @@ Global Variables
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
- ``block.chainid`` (``uint``): current chain id
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty
- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` that will be removed in the next breaking release
- ``block.gaslimit`` (``uint``): current block gaslimit
- ``block.number`` (``uint``): current block number
- ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``) (see `EIP-4399 <https://eips.ethereum.org/EIPS/eip-4399>`_ )
- ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch
- ``gasleft() returns (uint256)``: remaining gas
- ``msg.data`` (``bytes``): complete calldata
Expand Down
4 changes: 2 additions & 2 deletions docs/grammar/SolidityLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ YulEVMBuiltin:
| 'returndatacopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode'
| 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid'
| 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice'
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'gaslimit'
| 'basefee';
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao'
| 'gaslimit' | 'basefee';
YulLBrace: '{' -> pushMode(YulMode);
YulRBrace: '}' -> popMode;
Expand Down
7 changes: 4 additions & 3 deletions docs/units-and-global-variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ There are special variables and functions which always exist in the global
namespace and are mainly used to provide information about the blockchain
or are general-use utility functions.

.. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin
.. index:: abi, block, coinbase, difficulty, prevrandao, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin


Block and Transaction Properties
Expand All @@ -75,9 +75,10 @@ Block and Transaction Properties
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
- ``block.chainid`` (``uint``): current chain id
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty
- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` (`EIP-4399 <https://eips.ethereum.org/EIPS/eip-4399>`_ )
- ``block.gaslimit`` (``uint``): current block gaslimit
- ``block.number`` (``uint``): current block number
- ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``)
- ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch
- ``gasleft() returns (uint256)``: remaining gas
- ``msg.data`` (``bytes calldata``): complete calldata
Expand Down Expand Up @@ -394,4 +395,4 @@ These keywords are reserved in Solidity. They might become part of the syntax in
``define``, ``final``, ``implements``, ``in``, ``inline``, ``let``, ``macro``, ``match``,
``mutable``, ``null``, ``of``, ``partial``, ``promise``, ``reference``, ``relocatable``,
``sealed``, ``sizeof``, ``static``, ``supports``, ``switch``, ``typedef``, ``typeof``,
``var``.
``var``.
12 changes: 8 additions & 4 deletions docs/yul.rst
Original file line number Diff line number Diff line change
Expand Up @@ -751,8 +751,8 @@ This document does not want to be a full description of the Ethereum virtual mac
Please refer to a different document if you are interested in the precise semantics.

Opcodes marked with ``-`` do not return a result and all others return exactly one value.
Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I`` and ``L`` are present since Frontier, Homestead,
Byzantium, Constantinople, Istanbul or London respectively.
Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L`` and ``P`` are present since Frontier,
Homestead, Byzantium, Constantinople, Istanbul, London or Paris respectively.

In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to
but not including position ``b`` and ``storage[p]`` signifies the storage contents at slot ``p``.
Expand Down Expand Up @@ -931,6 +931,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a
+-------------------------+-----+---+-----------------------------------------------------------------+
| difficulty() | | F | difficulty of the current block (see note below) |
+-------------------------+-----+---+-----------------------------------------------------------------+
| prevrandao() | | P | randomness provided by the beacon chain (see note below) |
+-------------------------+-----+---+-----------------------------------------------------------------+
| gaslimit() | | F | block gas limit of the current block |
+-------------------------+-----+---+-----------------------------------------------------------------+

Expand All @@ -945,8 +947,10 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a
The remaining bytes will retain their values as of before the call.

.. note::
With the Paris network upgrade the semantics of ``difficulty`` have been changed.
It returns the value of ``prevrandao``, which is a 256-bit value, whereas the highest recorded
The `difficulty()` instruction is disallowed in EVM version >= Paris.
With the Paris network upgrade the semantics of the instruction that was previously called
``difficulty`` have been changed and the instruction was renamed to ``prevrandao``.
It can now return arbitrary values in the full 256-bit range, whereas the highest recorded
difficulty value within Ethash was ~54 bits.
This change is described in `EIP-4399 <https://eips.ethereum.org/EIPS/eip-4399>`_.
Please note that irrelevant to which EVM version is selected in the compiler, the semantics of
Expand Down
2 changes: 1 addition & 1 deletion libevmasm/Assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
sourceIndex = static_cast<int>(iter->second);
}

auto [name, data] = item.nameAndData();
auto [name, data] = item.nameAndData(m_evmVersion);
Json::Value jsonItem;
jsonItem["name"] = name;
jsonItem["begin"] = item.location().start;
Expand Down
5 changes: 4 additions & 1 deletion libevmasm/Assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ using AssemblyPointer = std::shared_ptr<Assembly>;
class Assembly
{
public:
Assembly(bool _creation, std::string _name): m_creation(_creation), m_name(std::move(_name)) { }
Assembly(langutil::EVMVersion _evmVersion, bool _creation, std::string _name): m_evmVersion(_evmVersion), m_creation(_creation), m_name(std::move(_name)) { }

AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); }
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
Expand Down Expand Up @@ -112,6 +112,7 @@ class Assembly
/// Changes the source location used for each appended item.
void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; }
langutil::SourceLocation const& currentSourceLocation() const { return m_currentSourceLocation; }
langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }

/// Assembles the assembly into bytecode. The assembly should not be modified after this call, since the assembled version is cached.
LinkerObject const& assemble() const;
Expand Down Expand Up @@ -208,6 +209,8 @@ class Assembly
mutable LinkerObject m_assembledObject;
mutable std::vector<size_t> m_tagPositionsInBytecode;

langutil::EVMVersion m_evmVersion;

int m_deposit = 0;
/// True, if the assembly contains contract creation code.
bool const m_creation = false;
Expand Down
17 changes: 11 additions & 6 deletions libevmasm/AssemblyItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const
return make_pair(subId, tag);
}

pair<string, string> AssemblyItem::nameAndData() const
pair<string, string> AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const
{
switch (type())
{
case Operation:
return {instructionInfo(instruction()).name, m_data != nullptr ? toStringInHex(*m_data) : ""};
return {instructionInfo(instruction(), _evmVersion).name, m_data != nullptr ? toStringInHex(*m_data) : ""};
case Push:
return {"PUSH", toStringInHex(data())};
case PushTag:
Expand Down Expand Up @@ -168,7 +168,9 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision)
size_t AssemblyItem::arguments() const
{
if (type() == Operation)
return static_cast<size_t>(instructionInfo(instruction()).args);
// The latest EVMVersion is used here, since the InstructionInfo is assumed to be
// the same across all EVM versions except for the instruction name.
return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).args);
else if (type() == VerbatimBytecode)
return get<0>(*m_verbatimBytecode);
else if (type() == AssignImmutable)
Expand All @@ -182,7 +184,9 @@ size_t AssemblyItem::returnValues() const
switch (m_type)
{
case Operation:
return static_cast<size_t>(instructionInfo(instruction()).ret);
// The latest EVMVersion is used here, since the InstructionInfo is assumed to be
// the same across all EVM versions except for the instruction name.
return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).ret);
case Push:
case PushTag:
case PushData:
Expand Down Expand Up @@ -251,7 +255,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
case Operation:
{
assertThrow(isValidInstruction(instruction()), AssemblyException, "Invalid instruction.");
text = util::toLower(instructionInfo(instruction()).name);
text = util::toLower(instructionInfo(instruction(), _assembly.evmVersion()).name);
break;
}
case Push:
Expand Down Expand Up @@ -323,12 +327,13 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
return text;
}

// Note: This method is exclusively used for debugging.
ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
{
switch (_item.type())
{
case Operation:
_out << " " << instructionInfo(_item.instruction()).name;
_out << " " << instructionInfo(_item.instruction(), EVMVersion()).name;
if (_item.instruction() == Instruction::JUMP || _item.instruction() == Instruction::JUMPI)
_out << "\t" << _item.getJumpTypeAsString();
break;
Expand Down
3 changes: 2 additions & 1 deletion libevmasm/AssemblyItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ class AssemblyItem

/// This function is used in `Assembly::assemblyJSON`.
/// It returns the name & data of the current assembly item.
/// @param _evmVersion the EVM version.
/// @returns a pair, where the first element is the json-assembly
/// item name, where second element is the string representation
/// of it's data.
std::pair<std::string, std::string> nameAndData() const;
std::pair<std::string, std::string> nameAndData(langutil::EVMVersion _evmVersion) const;

bytes const& verbatimData() const { assertThrow(m_type == VerbatimBytecode, util::Exception, ""); return std::get<2>(*m_verbatimBytecode); }

Expand Down
4 changes: 2 additions & 2 deletions libevmasm/CommonSubexpressionEliminator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,15 +406,15 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
m_stack.erase(m_stackHeight - static_cast<int>(i));
}
appendItem(*expr.item);
if (expr.item->type() != Operation || instructionInfo(expr.item->instruction()).ret == 1)
if (expr.item->type() != Operation || instructionInfo(expr.item->instruction(), EVMVersion()).ret == 1)
{
m_stack[m_stackHeight] = _c;
m_classPositions[_c].insert(m_stackHeight);
}
else
{
assertThrow(
instructionInfo(expr.item->instruction()).ret == 0,
instructionInfo(expr.item->instruction(), EVMVersion()).ret == 0,
OptimizerException,
"Invalid number of return values."
);
Expand Down
12 changes: 6 additions & 6 deletions libevmasm/ConstantOptimiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
return optimisations;
}

bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, langutil::EVMVersion _evmVersion)
{
bigint gas = 0;
for (AssemblyItem const& item: _items)
if (item.type() == Push)
gas += GasMeter::runGas(Instruction::PUSH1);
gas += GasMeter::runGas(Instruction::PUSH1, _evmVersion);
else if (item.type() == Operation)
{
if (item.instruction() == Instruction::EXP)
gas += GasCosts::expGas;
else
gas += GasMeter::runGas(item.instruction());
gas += GasMeter::runGas(item.instruction(), _evmVersion);
}
return gas;
}
Expand Down Expand Up @@ -131,7 +131,7 @@ void ConstantOptimisationMethod::replaceConstants(
bigint LiteralMethod::gasNeeded() const
{
return combineGas(
simpleRunGas({Instruction::PUSH1}),
simpleRunGas({Instruction::PUSH1}, m_params.evmVersion),
// PUSHX plus data
(m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas) + dataGas(toCompactBigEndian(m_value, 1)),
0
Expand All @@ -142,7 +142,7 @@ bigint CodeCopyMethod::gasNeeded() const
{
return combineGas(
// Run gas: we ignore memory increase costs
simpleRunGas(copyRoutine()) + GasCosts::copyGas,
simpleRunGas(copyRoutine(), m_params.evmVersion) + GasCosts::copyGas,
// Data gas for copy routines: Some bytes are zero, but we ignore them.
bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas),
// Data gas for data itself
Expand Down Expand Up @@ -322,7 +322,7 @@ bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
{
auto numExps = static_cast<size_t>(count(_routine.begin(), _routine.end(), Instruction::EXP));
return combineGas(
simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)),
simpleRunGas(_routine, m_params.evmVersion) + numExps * (GasCosts::expGas + GasCosts::expByteGas(m_params.evmVersion)),
// Data gas for routine: Some bytes are zero, but we ignore them.
bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas(m_params.evmVersion) : GasCosts::createDataGas),
0
Expand Down
2 changes: 1 addition & 1 deletion libevmasm/ConstantOptimiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ConstantOptimisationMethod

protected:
/// @returns the run gas for the given items ignoring special gas costs
static bigint simpleRunGas(AssemblyItems const& _items);
static bigint simpleRunGas(AssemblyItems const& _items, langutil::EVMVersion _evmVersion);
/// @returns the gas needed to store the given data literally
bigint dataGas(bytes const& _data) const;
static size_t bytesRequired(AssemblyItems const& _items);
Expand Down
9 changes: 5 additions & 4 deletions libevmasm/Disassemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ using namespace solidity::evmasm;

void solidity::evmasm::eachInstruction(
bytes const& _mem,
langutil::EVMVersion _evmVersion,
function<void(Instruction,u256 const&)> const& _onInstruction
)
{
Expand All @@ -38,7 +39,7 @@ void solidity::evmasm::eachInstruction(
Instruction const instr{*it};
int additional = 0;
if (isValidInstruction(instr))
additional = instructionInfo(instr).additional;
additional = instructionInfo(instr, _evmVersion).additional;

u256 data{};

Expand All @@ -57,15 +58,15 @@ void solidity::evmasm::eachInstruction(
}
}

string solidity::evmasm::disassemble(bytes const& _mem, string const& _delimiter)
string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, string const& _delimiter)
{
stringstream ret;
eachInstruction(_mem, [&](Instruction _instr, u256 const& _data) {
eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) {
if (!isValidInstruction(_instr))
ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;
else
{
InstructionInfo info = instructionInfo(_instr);
InstructionInfo info = instructionInfo(_instr, _evmVersion);
ret << info.name;
if (info.additional)
ret << " 0x" << std::uppercase << std::hex << _data;
Expand Down
4 changes: 2 additions & 2 deletions libevmasm/Disassemble.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace solidity::evmasm
{

/// Iterate through EVM code and call a function on each instruction.
void eachInstruction(bytes const& _mem, std::function<void(Instruction, u256 const&)> const& _onInstruction);
void eachInstruction(bytes const& _mem, langutil::EVMVersion _evmVersion, std::function<void(Instruction, u256 const&)> const& _onInstruction);

/// Convert from EVM code to simple EVM assembly language.
std::string disassemble(bytes const& _mem, std::string const& _delimiter = " ");
std::string disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, std::string const& _delimiter = " ");

}
Loading

0 comments on commit fd9ac9a

Please sign in to comment.