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

Lowered Safety Checker Gas #218

Merged
merged 46 commits into from
Aug 27, 2020
Merged

Lowered Safety Checker Gas #218

merged 46 commits into from
Aug 27, 2020

Conversation

K-Ho
Copy link
Contributor

@K-Ho K-Ho commented Aug 18, 2020

Description

All credit goes to @geohot! #214
Lower Safety Checker gas to <1.5m gas for 24KB contracts.
This just extends the above PR with fixed tests and comments.

Contributing Agreement

@karlfloersch
Copy link
Contributor

@K-Ho looks like a bunch of json files are committed?

@K-Ho
Copy link
Contributor Author

K-Ho commented Aug 18, 2020

@K-Ho looks like a bunch of json files are committed?

It's for the Safety Checker tests to verify that every compiled Synthetix contract is safe. There could be better ways to access the JSON files than just committing them to the main repo though.

Copy link

@willmeister willmeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looked at the contract code. Could use a bit of clarity in naming + comments. Added a few comments with more detail.

// current opcode: 0x00...0xff
uint256 op = uint8(_bytecode[pc]);
uint256 op;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would change this to opNumber

Comment on lines 50 to 61
uint256 _opcodeProcMask = ~uint256(0xffffffffffffffffffffffe000000000fffffffff070ffff9c0ffffec000f001);
// Halting opcodes
uint256 _opcodeStopMask = ~uint256(0x6008000000000000000000000000000000000000004000000000000000000001);
// PUSH opcodes
uint256 _opcodePushMask = ~uint256(0xffffffff000000000000000000000000);

uint256 codeLength;
uint256 _pc;
assembly {
_pc := add(_bytecode, 0x20)
}
codeLength = _pc + _bytecode.length;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why these local variables are not consistently named (_varName vs name)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point! Fixed all the other variable names, but I just tried replacing _pc with pc and this does not work in assembly, where pc refers to the PC opcode

// 4. CALL
// inline assembly removes the extra add + bounds check
assembly {
let tmp := mload(_pc)
Copy link

@willmeister willmeister Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would rename tmp to bytecodeStart or something that indicates what it is if that's not it.

if (gasOp >= 0x60 && gasOp <= 0x7f) {
pushedBytes = gasOp - 0x5f;
}
let mpc := byte(0, mload(add(skip, byte(0, tmp))))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mpc seems like it stands for something. Would rename it to be something that indicates what that is.

if (opBit & _opcodeProcMask == 0) {
if (opBit & _opcodePushMask == 0) {
// subsequent bytes are not opcodes. Skip them.
_pc += (op - 0x5e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might create a const for 0x5e. I assume that's the opcode before PUSH1? Maybe named pushStart?

Comment on lines 40 to 48
uint256[8] memory skip = [
uint256(0x0001010101010101010101010000000001010101010101010101010101010000),
uint256(0x0100000000000000000000000000000000000000010101010101000000010100),
uint256(0x0000000000000000000000000000000001010101000000010101010100000000),
uint256(0x0203040500000000000000000000000000000000000000000000000000000000),
uint256(0x0101010101010101010101010101010101010101010101010101010101010101),
uint256(0x0101010101000000000000000000000000000000000000000000000000000000),
uint256(0x0000000000000000000000000000000000000000000000000000000000000000),
uint256(0x0000000000000000000000000000000000000000000000000000000000000000)];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this is a uint256[8] instead of just bytes? I think it can just be a bytes literal: ethereum/solidity#832

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't work with the way he's operating on it, unfortunately :(

Comment on lines 70 to 75
let mpc := byte(0, mload(add(skip, byte(0, tmp))))
mpc := add(mpc, byte(0, mload(add(skip, byte(mpc, tmp)))))
mpc := add(mpc, byte(0, mload(add(skip, byte(mpc, tmp)))))
mpc := add(mpc, byte(0, mload(add(skip, byte(mpc, tmp)))))
mpc := add(mpc, byte(0, mload(add(skip, byte(mpc, tmp)))))
mpc := add(mpc, byte(0, mload(add(skip, byte(mpc, tmp)))))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's very unclear what this is supposed to do. A few comments here and/or better naming would be useful.

// encountered a JUMPDEST
if (op == 0x5b) break;
// skip PUSHed bytes
if ((1 << op) & _opcodePushMask == 0) _pc += (op - 0x5f);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can re-use pushStart const here if created (see comment above)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried this out, unfortunately, increases gas cost, so I added a comment instead

if ((1 << op) & _opcodePushMask == 0) _pc += (op - 0x5f);
} while (_pc < codeLength);
// op is 0x5b, so we don't continue here since the _pc++ is fine
} else if (op == 0x33) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else if (op == 0x33) {
} else if (op == 0x33) { // CALLER opcode

for (uint256 pc = 0; pc < _bytecode.length; pc++) {
// autogenerated by gen_safety_checker_constants.py
// number of bytes to skip for each opcode
uint256[8] memory skip = [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would rename to something better than skip. Maybe opcodeBytesConsumed?

Copy link

@willmeister willmeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@Jinglan Jinglan merged commit eb6ae3a into master Aug 27, 2020
@K-Ho K-Ho deleted the LowerSafetyCheckerGas branch September 1, 2020 20:31
bap2pecs pushed a commit to babylonlabs-io/optimism that referenced this pull request Jul 31, 2024
We don't have private dependencies anymore.
bap2pecs pushed a commit to babylonlabs-io/optimism that referenced this pull request Jul 31, 2024
* Init
* Update babylon-private reference
* Revert "CI: Remove redundant SSH key logic (ethereum-optimism#218)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants