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

Adding MCOPY Instruction #2711

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft

Adding MCOPY Instruction #2711

wants to merge 12 commits into from

Conversation

nagarev
Copy link
Contributor

@nagarev nagarev commented Sep 5, 2024

Description

Besides memory copying being a basic operation, implementing it on the VM comes with overhead, as described in the EIP-5656

Currently memory copying can be achieved by the usage of CALL, MLOAD and MSTORE (among others opcodes) depending on the scenarios where the memory copy is being done.

The MCOPY instruction will be introduced at 0x5E.

Motivation and Context

Increase compatibility

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • Tests for the changes have been added (for bug fixes / features)
  • Requires Activation Code (Hard Fork)
  • Other information:

N/A

fmacleal
fmacleal previously approved these changes Sep 19, 2024
Copy link
Contributor

@fmacleal fmacleal left a comment

Choose a reason for hiding this comment

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

Good job. Simple, straight to the point and with an amazing test. Well done!

// gas cost = 3 * (length + 31) + memory expansion cost + very low
long length = stack.get(stack.size() - 3).longValue();
long newMemSize = memNeeded(stack.peek(), length);
long cost = 3 * (length + 31) + calcMemGas(oldMemSize, newMemSize, 0) + 3; // TODO -> Check copy size
Copy link
Contributor

Choose a reason for hiding this comment

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

In order to calculate the number of words we are missing to divide the total size by the dataword length being (length + 31) / 32 instead of only (length + 31) .
Also I think it is more readable if we store the different values separated adding a meaningful name to them

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice! will continue with this in the next PR. 💪🏼

fmacleal
fmacleal previously approved these changes Sep 27, 2024
Copy link
Contributor

@fmacleal fmacleal left a comment

Choose a reason for hiding this comment

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

Nice job!
Really liked the organization from DSL tests and the tests itself, well done!

DataWord length = program.stackPop();

if (isLogEnabled) {
hint = "dst: " + dst + " src: " + src + " length: " + length;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

I noticed that you are not logging at the end, maybe would be good to log these parameters that you set.

Copy link
Contributor

Choose a reason for hiding this comment

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

Take a look at this comment @nagarev. :)

Copy link
Contributor

@fmacleal fmacleal left a comment

Choose a reason for hiding this comment

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

Well done @nagarev. These tests are pretty complete and shows a hard work in fulfil the scenarios of test from the EIP.

I just have a few comments to improve it even more the readability. But they are not blocking and doesn't prevent the approval.

You need to fix some tests though, it seems that it's broke for java-17 and java-21.

Comment on lines +1441 to +1442
// See "Gas Cost" section on EIP 5656
// gas cost = 3 * (length + 31) + memory expansion cost + very low
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

The part very low isn't clear as long as we read the EIP. I suggest you rephrase it. Maybe to gas fixed for very low mem usage. Or just put it plainly 3.

DataWord length = program.stackPop();

if (isLogEnabled) {
hint = "dst: " + dst + " src: " + src + " length: " + length;
Copy link
Contributor

Choose a reason for hiding this comment

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

Take a look at this comment @nagarev. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

You are using meaningful names for the variables and methods, I think you don't need the comments explaining that you are checking that a block has a single transaction, or that that the transaction has a receipt. Let the code speak for itself, you are already using principles of clean code with good names for variables and methods, the comments can age badly and wouldn't be missed. 🙂

Comment on lines +38 to +55
// There's one block (b01) containing only 1 transaction
Block block1 = world.getBlockByName("b01");
Assertions.assertNotNull(block1);
Assertions.assertEquals(1, block1.getTransactionsList().size());

// There's a transaction called txTestMCopy
Transaction txTestMCopy = world.getTransactionByName("txTestMCopy");
Assertions.assertNotNull(txTestMCopy);

// Transaction txTestMCopy has a transaction receipt
TransactionReceipt txTestMCopyReceipt = world.getTransactionReceiptByName("txTestMCopy");
Assertions.assertNotNull(txTestMCopyReceipt);

// Transaction txTestMCopy has been processed correctly
byte[] creationStatus = txTestMCopyReceipt.getStatus();
Assertions.assertNotNull(creationStatus);
Assertions.assertEquals(1, creationStatus.length);
Assertions.assertEquals(1, creationStatus[0]);
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

You could extract these assertions to a method, because they are repeating thoroughly in your class. Something like this one here could do the job.v Be aware that you might need to adapt this methid, since you might have transactionReceipt but with the length 0.

// https://github.com/ethereum/execution-spec-tests/blob/c0065176a79f89d93f4c326186fc257ec5b8d5f1/tests/cancun/eip5656_mcopy/test_mcopy.py)

@Test
void testMCOPY_overwriteCases_behaveAsExpected() throws FileNotFoundException, DslProcessorException {
Copy link
Contributor

Choose a reason for hiding this comment

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

praise:

Well done my friend, this test it's very complete and it should have been a bit tricky understand the python one and convert it to a proper DSL. 👏

Copy link

github-actions bot commented Nov 4, 2024

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails

Scanned Manifest Files

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.

3 participants