Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

1700 push zero #1709

Merged
merged 12 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libconsensus
DmytroNazarenko marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions libethcore/ChainOperationParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ struct SChain {
time_t verifyDaSigsPatchTimestamp = 0;
time_t storageDestructionPatchTimestamp = 0;
time_t powCheckPatchTimestamp = 0;
time_t pushZeroPatchTimestamp = 0;
time_t skipInvalidTransactionsPatchTimestamp = 0;

SChain() {
Expand Down
4 changes: 4 additions & 0 deletions libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ ChainParams ChainParams::loadConfig(
sChainObj.at( "powCheckPatchTimestamp" ).get_int64() :
0;

s.pushZeroPatchTimestamp = sChainObj.count( "pushZeroPatchTimestamp" ) ?
sChainObj.at( "pushZeroPatchTimestamp" ).get_int64() :
0;

s.skipInvalidTransactionsPatchTimestamp =
sChainObj.count( "skipInvalidTransactionsPatchTimestamp" ) ?
sChainObj.at( "skipInvalidTransactionsPatchTimestamp" ).get_int64() :
Expand Down
3 changes: 3 additions & 0 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <libskale/ContractStorageLimitPatch.h>
#include <libskale/ContractStorageZeroValuePatch.h>
#include <libskale/POWCheckPatch.h>
#include <libskale/PushZeroPatch.h>
#include <libskale/RevertableFSPatch.h>
#include <libskale/SkipInvalidTransactionsPatch.h>
#include <libskale/State.h>
Expand Down Expand Up @@ -163,6 +164,7 @@ Client::Client( ChainParams const& _params, int _networkID,
RevertableFSPatch::setTimestamp( chainParams().sChain.revertableFSPatchTimestamp );
StorageDestructionPatch::setTimestamp( chainParams().sChain.storageDestructionPatchTimestamp );
POWCheckPatch::setTimestamp( chainParams().sChain.powCheckPatchTimestamp );
PushZeroPatch::setTimestamp( chainParams().sChain.pushZeroPatchTimestamp );
SkipInvalidTransactionsPatch::setTimestamp(
this->chainParams().sChain.skipInvalidTransactionsPatchTimestamp );
}
Expand Down Expand Up @@ -657,6 +659,7 @@ size_t Client::syncTransactions(
RevertableFSPatch::lastBlockTimestamp = blockChain().info().timestamp();
StorageDestructionPatch::lastBlockTimestamp = blockChain().info().timestamp();
POWCheckPatch::lastBlockTimestamp = blockChain().info().timestamp();
PushZeroPatch::lastBlockTimestamp = blockChain().info().timestamp();
SkipInvalidTransactionsPatch::lastBlockTimestamp = blockChain().info().timestamp();

DEV_WRITE_GUARDED( x_working ) {
Expand Down
2 changes: 2 additions & 0 deletions libethereum/ValidationSchemes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ void validateConfigJson( js::mObject const& _obj ) {
{ "storageDestructionPatchTimestamp",
{ { js::int_type }, JsonFieldPresence::Optional } },
{ "powCheckPatchTimestamp", { { js::int_type }, JsonFieldPresence::Optional } },
{ "pushZeroPatchTimestamp", { { js::int_type }, JsonFieldPresence::Optional } },
{ "nodeGroups", { { js::obj_type }, JsonFieldPresence::Optional } },
{ "nodeGroups", { { js::obj_type }, JsonFieldPresence::Optional } },
{ "skipInvalidTransactionsPatchTimestamp",
{ { js::int_type }, JsonFieldPresence::Optional } } } );
Expand Down
4 changes: 4 additions & 0 deletions libevm/Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::MSIZE, { "MSIZE", 0, 1, Tier::Base } },
{ Instruction::GAS, { "GAS", 0, 1, Tier::Base } },
{ Instruction::JUMPDEST, { "JUMPDEST", 0, 0, Tier::Special } },
// As per EIP-3855 PUSH0 instruction tire is base (2 gas units)
// As all other PUSH instructions, it removes zero elements from stack and
// pushes 1 element to stack
{ Instruction::PUSH0, { "PUSH0", 0, 1, Tier::Base } },
{ Instruction::PUSH1, { "PUSH1", 0, 1, Tier::VeryLow } },
{ Instruction::PUSH2, { "PUSH2", 0, 1, Tier::VeryLow } },
{ Instruction::PUSH3, { "PUSH3", 0, 1, Tier::VeryLow } },
Expand Down
1 change: 1 addition & 0 deletions libevm/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum class Instruction : uint8_t {
GAS, ///< get the amount of available gas
JUMPDEST, ///< set a potential jump destination

PUSH0 = 0x5f, // EIP-3855
PUSH1 = 0x60, ///< place 1 byte item on stack
PUSH2, ///< place 2 byte item on stack
PUSH3, ///< place 3 byte item on stack
Expand Down
16 changes: 16 additions & 0 deletions libevm/LegacyVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "LegacyVM.h"
#include "libskale/PushZeroPatch.h"

using namespace std;
using namespace dev;
Expand Down Expand Up @@ -1355,6 +1356,21 @@
}
CONTINUE

// EIP-3855. Code PUSH0 is similar to PUSH1 but pushes 0
// we need to increment program counter only by one since
// the value is not read from program code as in PUSH1
CASE( PUSH0 ) {
if ( !PushZeroPatch::isEnabled() ) {
DmytroNazarenko marked this conversation as resolved.
Show resolved Hide resolved
throwBadInstruction();

Check warning on line 1364 in libevm/LegacyVM.cpp

View check run for this annotation

Codecov / codecov/patch

libevm/LegacyVM.cpp#L1362-L1364

Added lines #L1362 - L1364 were not covered by tests
}
ON_OP();
updateIOGas();
m_SPP[0] = 0;
++m_PC;

Check warning on line 1369 in libevm/LegacyVM.cpp

View check run for this annotation

Codecov / codecov/patch

libevm/LegacyVM.cpp#L1366-L1369

Added lines #L1366 - L1369 were not covered by tests
};
CONTINUE

Check warning on line 1371 in libevm/LegacyVM.cpp

View check run for this annotation

Codecov / codecov/patch

libevm/LegacyVM.cpp#L1371

Added line #L1371 was not covered by tests


CASE( PUSH1 ) {
ON_OP();
updateIOGas();
Expand Down
2 changes: 1 addition & 1 deletion libevm/LegacyVMConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ namespace eth {
&&BEGINDATA, \
&&BEGINSUB, \
&&INVALID, \
&&INVALID, \
&&PUSH0, /* EIP-3855 */ \
&&PUSH1, /* 60, */ \
&&PUSH2, \
&&PUSH3, \
Expand Down
1 change: 1 addition & 0 deletions libskale/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set(sources
OverlayFS.cpp
StorageDestructionPatch.cpp
POWCheckPatch.cpp
PushZeroPatch.cpp
SkipInvalidTransactionsPatch.cpp
)

Expand Down
11 changes: 11 additions & 0 deletions libskale/PushZeroPatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "PushZeroPatch.h"

time_t PushZeroPatch::pushZeroPatchTimestamp;
time_t PushZeroPatch::lastBlockTimestamp;

bool PushZeroPatch::isEnabled() {
if ( pushZeroPatchTimestamp == 0 ) {
return false;

Check warning on line 8 in libskale/PushZeroPatch.cpp

View check run for this annotation

Codecov / codecov/patch

libskale/PushZeroPatch.cpp#L6-L8

Added lines #L6 - L8 were not covered by tests
}
return pushZeroPatchTimestamp <= lastBlockTimestamp;

Check warning on line 10 in libskale/PushZeroPatch.cpp

View check run for this annotation

Codecov / codecov/patch

libskale/PushZeroPatch.cpp#L10

Added line #L10 was not covered by tests
}
27 changes: 27 additions & 0 deletions libskale/PushZeroPatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <libethereum/SchainPatch.h>
#include <time.h>

namespace dev {
namespace eth {
class Client;
}
} // namespace dev

/*
* Context: enable effective storage destruction
*/
class PushZeroPatch : public SchainPatch {
public:
static bool isEnabled();

static void setTimestamp( time_t _timeStamp ) {
printInfo( __FILE__, _timeStamp );
pushZeroPatchTimestamp = _timeStamp;
}


private:
friend class dev::eth::Client;
static time_t pushZeroPatchTimestamp;
static time_t lastBlockTimestamp;
};
3 changes: 2 additions & 1 deletion test/historicstate/configs/basic_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,11 @@
"sChain":
{
"schainName": "TestChain",
"schainID": 1,
"schainID": 5,
"schainOwner": "0x907cd0881E50d359bb9Fd120B1A5A143b1C97De6",
"contractStorageLimit": 10000000000,
"emptyBlockIntervalMs": 10000,
"pushZeroPatchTimestamp": 1,
"nodes": [
{ "nodeID": 1112, "ip": "127.0.0.1", "basePort": 1231, "schainIndex" : 1, "publicKey":""}
]
Expand Down
15 changes: 15 additions & 0 deletions test/historicstate/hardhat/contracts/Push0.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Push0 {

uint256 public constant ZERO = 0;

function getZero() public {
// this triggers compiler using push0 to stack since operations use lots of zeros
uint256 one = 0;
one = one + 1 + ZERO;
uint256 two = one * 0;
uint256 three = one * ZERO;
}
}
2 changes: 1 addition & 1 deletion test/historicstate/hardhat/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
const INSECURE_PRIVATE_KEY = "bd200f4e7f597f3c2c77fb405ee7fabeb249f63f03f43d5927b4fa0c43cfe85e";

module.exports = {
solidity: "0.8.9",
solidity: "0.8.20",
networks: {
skaled: {
url: `http://localhost:1234`,
Expand Down
84 changes: 84 additions & 0 deletions test/historicstate/hardhat/scripts/push0_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const OWNER_ADDRESS: string = "0x907cd0881E50d359bb9Fd120B1A5A143b1C97De6";
const ZERO_ADDRESS: string = "0xO000000000000000000000000000000000000000";
const INITIAL_MINT: bigint = 10000000000000000000000000000000000000000n;

import {ethers} from "hardhat";

async function waitUntilNextBlock() {

const current = await hre.ethers.provider.getBlockNumber();
let newBlock = current;
console.log(`BLOCK_NUMBER ${current}`);

while (newBlock == current) {
newBlock = await hre.ethers.provider.getBlockNumber();
}

console.log(`BLOCK_NUMBER ${newBlock}`);

return current;

}

function CHECK(result: any): void {
if (!result) {
const message: string = `Check failed ${result}`
console.log(message);
throw message;
}
}

async function getAndPrintTrace(hash: string): Promise<String> {
// const trace = await ethers.provider.send('debug_traceTransaction', [hash, {"tracer":"prestateTracer",
// "tracerConfig": {"diffMode":true}}]);

// const trace = await ethers.provider.send('debug_traceTransaction', [hash, {"tracer": "callTracer",
// "tracerConfig": {"withLog":true}}]);
DmytroNazarenko marked this conversation as resolved.
Show resolved Hide resolved

const trace = await ethers.provider.send('debug_traceTransaction', [hash, {}]);



console.log(JSON.stringify(trace, null, 4));
return trace;
}

async function deployWriteAndDestroy(): Promise<void> {

console.log(`Deploying ...`);

const Push0Test = await ethers.getContractFactory("Push0");
const test = await Push0Test.deploy();
const testContract = await test.deployed();


const deployBn = await ethers.provider.getBlockNumber();

const hash = testContract.deployTransaction.hash;
console.log(`Gas limit ${testContract.deployTransaction.gasLimit}`);
console.log(`Contract deployed to ${testContract.address} at block ${deployBn} tx hash ${hash}`);


// await waitUntilNextBlock()

//await getAndPrintTrace(hash)
DmytroNazarenko marked this conversation as resolved.
Show resolved Hide resolved


console.log(`Now testing`);

const transferReceipt = await testContract.getZero()
console.log(`Gas limit ${transferReceipt.gasLimit}`);


}

async function main(): Promise<void> {
await deployWriteAndDestroy();
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error: any) => {
console.error(error);
process.exitCode = 1;
});
Loading