Skip to content
New issue

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

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

Already on GitHub? # to your account

Charge gas for EEI methods #86

Merged
merged 1 commit into from
Mar 5, 2018
Merged

Charge gas for EEI methods #86

merged 1 commit into from
Mar 5, 2018

Conversation

jakelang
Copy link
Member

@jakelang jakelang commented Jan 16, 2018

Fixes #74.

src/eei.h Outdated
@@ -108,8 +108,18 @@ struct EthereumInterface : ShellExternalInterface {
};

struct GasSchedule {
static constexpr unsigned sLoad = 50;
Copy link
Member

Choose a reason for hiding this comment

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

Should be called storageLoad

src/eei.h Outdated
static constexpr unsigned create = 32000;
static constexpr unsigned call = 40;
static constexpr unsigned memory = 3;
static constexpr unsigned copy = 3;
Copy link
Member

Choose a reason for hiding this comment

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

What are these two used for?

Copy link
Member Author

Choose a reason for hiding this comment

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

They are used in codecopy and calldatacopy, according to outdated yellowpaper semantics. Will fix this

Copy link
Member

Choose a reason for hiding this comment

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

Can you name perhaps have codeMemory, codeCopy and callDataMemory, callDataCopy?

Copy link
Member Author

@jakelang jakelang Jan 17, 2018

Choose a reason for hiding this comment

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

yeah, I was using the fee schedule names from EVMJIT and the yellowpaper but this makes more sense i guess.

EDIT: It does not make sense to do this because gas costs are tiered. going to use EVMJIT style naming.

@jakelang jakelang force-pushed the eei-gas-charge branch 7 times, most recently from de060bf to 6cc69b2 Compare January 17, 2018 22:06
@axic axic changed the title [WIP] Charge gas for EEI methods Charge gas for EEI methods Jan 18, 2018
@axic axic requested a review from chfast January 18, 2018 02:46
Copy link
Collaborator

@chfast chfast left a comment

Choose a reason for hiding this comment

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

In general, you subtract gas before execution an instruction.

src/eei.cpp Outdated
@@ -209,6 +221,8 @@ namespace HeraVM {
vector<uint8_t> input(msg.input, msg.input + msg.input_size);
storeMemory(input, dataOffset, resultOffset, length);

takeGas(GasSchedule::stepGas2 + GasSchedule::copy * (length / 32));
Copy link
Collaborator

Choose a reason for hiding this comment

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

@axic What do you think about charging for memory per byte, instead of per "word"?
@jakelang I believe length / 32 should be rounded up, not down.

src/eei.cpp Outdated
@@ -241,12 +259,16 @@ namespace HeraVM {

storeMemory(code, codeOffset, resultOffset, length);

takeGas(GasSchedule::stepGas2 + GasSchedule::copy * (length / 32));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here.

src/eei.cpp Outdated
@@ -347,6 +382,8 @@ namespace HeraVM {

context->fn_table->log(context, &msg.address, data.data(), length, topics, numberOfTopics);

takeGas(GasSchedule::log + (length * GasSchedule::logData) + (GasSchedule::logTopic * numberOfTopics));
Copy link
Collaborator

Choose a reason for hiding this comment

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

How do you prevent overflows?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't see a solution to this that isn't messy.
Maybe a helper function would be better for this.

src/eei.cpp Outdated
if (import->base == Name("call") && !context->fn_table->account_exists(context, &call_message.address))
takeGas(GasSchedule::callnewacct);

takeGas(GasSchedule::call);
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. This should go first, before other checks.
  2. Also, the gas should be taken before the actual call.
  3. You also have to take gas of the gas argument, and put back the amount left after the call.

src/eei.cpp Outdated
@@ -601,6 +661,9 @@ namespace HeraVM {
if (create_result.release)
create_result.release(&create_result);

takeGas(GasSchedule::create);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Must go before the CREATE.

src/eei.h Outdated
static constexpr unsigned stepGas4 = 8;
static constexpr unsigned stepGas5 = 10;
static constexpr unsigned stepGas6 = 20;
static constexpr unsigned stepGas7 = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why 0?

Copy link
Member Author

Choose a reason for hiding this comment

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

This was here:
https://github.com/ethereum/evmjit/blob/develop/libevmjit/JIT.h#L71

It is unneeded, so I am getting rid of it

@axic
Copy link
Member

axic commented Jan 18, 2018

@chfast do you want to review the costs and work on this to finish it?

@jakelang
Copy link
Member Author

@chfast I have made appropriate changes. I am also considering writing helpers for arithmetic overflow checking in gas charges.

src/eei.cpp Outdated
@@ -403,6 +438,7 @@ namespace HeraVM {
GasSchedule::storageStoreChange
);

context->fn_table->get_storage(&current, context, &msg.address, &path);
Copy link
Member

Choose a reason for hiding this comment

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

This must happen before takeGas otherwise it will charge invalidly.

@@ -550,6 +597,9 @@ namespace HeraVM {
if (call_result.release)
call_result.release(&call_result);

/* Return unspent gas */
result.gasLeft += call_result.gas_left;
Copy link
Member

Choose a reason for hiding this comment

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

For this to work, the entire passed gas must be used via takeGas before doing an EVM-C call.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is done by just performing:
takeGas(gas);
before the call execution, correct?

Copy link
Member

Choose a reason for hiding this comment

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

Yep

@jakelang jakelang force-pushed the eei-gas-charge branch 5 times, most recently from 7f6b298 to 0f983f0 Compare January 24, 2018 23:28
@axic
Copy link
Member

axic commented Jan 24, 2018

Please rebase, it is in conflict.

src/eei.cpp Outdated
@@ -470,20 +516,24 @@ namespace HeraVM {
uint32_t valueOffset;
uint32_t dataOffset;
uint32_t dataLength;
uint32_t resultOffset;
uint32_t resultLength;
Copy link
Member

Choose a reason for hiding this comment

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

These shouldn't need to be added back.

src/eei.cpp Outdated

heraAssert((msg.flags & ~EVM_STATIC) == 0, "Unknown flags not supported.");

evm_message call_message;
call_message.address = loadUint160(addressOffset);
call_message.flags = msg.flags;
call_message.code_hash = {};
call_message.gas = gas - (gas / 64);
call_message.gas = gas;
Copy link
Member

Choose a reason for hiding this comment

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

Please don't remove this.

src/eei.h Outdated
static constexpr unsigned blockhash = 800;
static constexpr unsigned balance = 400;
static constexpr unsigned stepGas0 = 0;
static constexpr unsigned stepGas1 = 2;
Copy link
Member

Choose a reason for hiding this comment

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

I think I'd prefer having named gas fields for each of the interface method as opposed to YellowPaper-esque stepGas*

Copy link
Member Author

Choose a reason for hiding this comment

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

any recommendations for a naming scheme?

Copy link
Member

Choose a reason for hiding this comment

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

Probably the name of the interface method?

Copy link
Member Author

Choose a reason for hiding this comment

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

Lots of these are used for multiple interface methods.

Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest to with the YP in that case: Appendix G of https://ethereum.github.io/yellowpaper/paper.pdf

@jakelang jakelang force-pushed the eei-gas-charge branch 5 times, most recently from c94412a to 6d3f9ad Compare January 25, 2018 00:52
src/eei.cpp Outdated

takeGas(create_message.gas);
takeGas(GasSchedule::create);
takeGas(GasSchedule::callnewacct);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not needed here. However, changing GasSchedule::create to be equal GasSchedule::call + GasSchedule::callnewacct would make sense, @axic ?

src/eei.cpp Outdated
@@ -598,6 +661,9 @@ namespace HeraVM {
if (create_result.release)
create_result.release(&create_result);

/* Return unspent gas */
result.gasLeft += create_result.gas_left;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure this is correct. This was not subtruck for CREATE case.

@jakelang jakelang force-pushed the eei-gas-charge branch 2 times, most recently from 05209c1 to 848ec17 Compare January 30, 2018 22:23
src/eei.cpp Outdated
@@ -516,7 +564,7 @@ namespace HeraVM {
addressOffset << " " <<
valueOffset << " " <<
dataOffset << " " <<
dataLength << dec << "\n";
dataLength << " " << dec << "\n";
Copy link
Member

Choose a reason for hiding this comment

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

I think this is not needed. dec as misleading it is (perhaps should used explicit std::dec here), is switching to decimal display mode for numbers

Copy link
Member Author

@jakelang jakelang Feb 4, 2018

Choose a reason for hiding this comment

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

This change is leftover from an old version of Hera. Will rebase against new master

src/eei.cpp Outdated
takeGas(GasSchedule::callnewacct);
if (!isZeroUint256(call_message.value))
takeGas(GasSchedule::valuetransfer);
takeGas(gas);
Copy link
Member

Choose a reason for hiding this comment

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

I think this actually should use call_message.gas because the all-but-1/64th rule applies to this too.

src/eei.h Outdated
static constexpr unsigned copy = 3;
static constexpr unsigned blockhash = 800;
static constexpr unsigned balance = 400;
static constexpr unsigned stepGas1 = 2;
Copy link
Member

Choose a reason for hiding this comment

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

Can you please use the names from the Yellowpapyer? veryLow, low, etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

Some of the gas charges in the are unused in EEI. Should they be retained in the gas schedule for the sake of yellowpaper compliance and potential later use, or trimmed off?

Copy link
Member

Choose a reason for hiding this comment

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

Just trimmed off.

src/eei.cpp Outdated
@@ -239,6 +254,9 @@ namespace HeraVM {

HERA_DEBUG << "codeCopy " << hex << resultOffset << " " << codeOffset << " " << length << dec << "\n";

heraAssert(ffs(GasSchedule::copy) + (ffs(length) - 5) <= 64, "Gas charge overflow");
heraAssert(numeric_limits<uint64_t>::max() - GasSchedule::stepGas2 >= GasSchedule::copy * (length / 32), "Gas charge overflow");
takeGas((uint64_t)ceil(GasSchedule::stepGas2 + GasSchedule::copy * (length / 32)));
Copy link
Member

Choose a reason for hiding this comment

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

This one uses ceil, but the one in externalCodeCopy doesn't. Any reason for that? Also shouldn't this instead just use (length + 31) / 32 to avoid the use of ceil?

Copy link
Member

Choose a reason for hiding this comment

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

It also may make sense creating a helper along the lines of takeWordCopyGas(baseCost, costPerWord, length)

Copy link
Member Author

@jakelang jakelang Feb 4, 2018

Choose a reason for hiding this comment

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

I will implement helpers in a separate PR if there is a significant need for it.

src/eei.cpp Outdated
@@ -206,6 +218,7 @@ namespace HeraVM {

HERA_DEBUG << "callDataCopy " << hex << resultOffset << " " << dataOffset << " " << length << dec << "\n";

takeGas(GasSchedule::stepGas2 + GasSchedule::copy * (length / 32));
Copy link
Member

Choose a reason for hiding this comment

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

The rules applied in codeCopy and externalCodeCopy are not really followed here?

@jakelang jakelang force-pushed the eei-gas-charge branch 2 times, most recently from 8663aee to 026de4b Compare February 4, 2018 20:41
src/eei.cpp Outdated
@@ -262,8 +285,10 @@ namespace HeraVM {
const uint8_t *code;
size_t code_size = context->fn_table->get_code(&code, context, &address);

heraAssert(ffs(GasSchedule::copy) + (ffs(length) - 5) <= 64, "Gas charge overflow");
heraAssert(numeric_limits<uint64_t>::max() - GasSchedule::extcode >= GasSchedule::copy * (length / 32), "Gas charge overflow");
Copy link
Member

Choose a reason for hiding this comment

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

The assertions don't use the same rounding for length?

@axic
Copy link
Member

axic commented Feb 14, 2018

@jakelang I hoped that @chfast could review the values but I'll do it tonight so we can stop dragging this PR forever. Will just fix issues as we go along.

src/eei.cpp Outdated
@@ -206,6 +218,10 @@ namespace HeraVM {

HERA_DEBUG << "callDataCopy " << hex << resultOffset << " " << dataOffset << " " << length << dec << "\n";

heraAssert(ffs(GasSchedule::copy) + (ffs(length) - 5) <= 64, "Gas charge overflow");
heraAssert(numeric_limits<uint64_t>::max() - GasSchedule::verylow >= GasSchedule::copy * ((static_cast<uint64_t>(length) + 31) / 32), "Gas charge overflow");
takeGas(GasSchedule::verylow + GasSchedule::copy * ((static_cast<uint64_t>(length) + 31) / 32));
Copy link
Member

Choose a reason for hiding this comment

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

I really think we should have a helper for this since there 3 copies now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Could open an issue for this and do it in a separate PR, possibly a refactoring pass.
Might as well get it working now.

Copy link
Collaborator

@chfast chfast left a comment

Choose a reason for hiding this comment

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

Looks good, just one C++ suggestion for future: if you widen a type e.g. from size_t to uint64_t, you can just do uint64_t(length). It is always safe. static_cast suggests you are discarding some information.

@jakelang jakelang force-pushed the eei-gas-charge branch 2 times, most recently from 5c9bf12 to 13145fb Compare February 21, 2018 19:37
@axic axic force-pushed the eei-gas-charge branch from 13145fb to cfc6518 Compare March 5, 2018 21:37
Use YellowPaper-style gas fee names
@axic axic force-pushed the eei-gas-charge branch from cfc6518 to e2a6838 Compare March 5, 2018 21:43
@axic axic merged commit cc11a88 into master Mar 5, 2018
@axic axic deleted the eei-gas-charge branch March 5, 2018 22:17
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants