-
Notifications
You must be signed in to change notification settings - Fork 51
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
Conversation
504054e
to
13f69a5
Compare
src/eei.h
Outdated
@@ -108,8 +108,18 @@ struct EthereumInterface : ShellExternalInterface { | |||
}; | |||
|
|||
struct GasSchedule { | |||
static constexpr unsigned sLoad = 50; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
de060bf
to
6cc69b2
Compare
There was a problem hiding this 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)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/eei.cpp
Outdated
@@ -241,12 +259,16 @@ namespace HeraVM { | |||
|
|||
storeMemory(code, codeOffset, resultOffset, length); | |||
|
|||
takeGas(GasSchedule::stepGas2 + GasSchedule::copy * (length / 32)); |
There was a problem hiding this comment.
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)); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This should go first, before other checks.
- Also, the gas should be taken before the actual call.
- 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); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why 0?
There was a problem hiding this comment.
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
@chfast do you want to review the costs and work on this to finish it? |
4852472
to
77fd2f4
Compare
@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(¤t, context, &msg.address, &path); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
7f6b298
to
0f983f0
Compare
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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*
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
c94412a
to
6d3f9ad
Compare
src/eei.cpp
Outdated
|
||
takeGas(create_message.gas); | ||
takeGas(GasSchedule::create); | ||
takeGas(GasSchedule::callnewacct); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
05209c1
to
848ec17
Compare
src/eei.cpp
Outdated
@@ -516,7 +564,7 @@ namespace HeraVM { | |||
addressOffset << " " << | |||
valueOffset << " " << | |||
dataOffset << " " << | |||
dataLength << dec << "\n"; | |||
dataLength << " " << dec << "\n"; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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))); |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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)); |
There was a problem hiding this comment.
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?
8663aee
to
026de4b
Compare
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"); |
There was a problem hiding this comment.
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?
41630c6
to
ae62b74
Compare
6eb808c
to
a7229de
Compare
a7229de
to
ce54bad
Compare
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)); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
5c9bf12
to
13145fb
Compare
Use YellowPaper-style gas fee names
Fixes #74.