-
Notifications
You must be signed in to change notification settings - Fork 486
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
Fix padding and gas cost computation issues in precompiles #961
Fix padding and gas cost computation issues in precompiles #961
Conversation
}); | ||
} | ||
let mut buf = [0u8; 32]; | ||
let mut input_iter = input[start_inx..].iter().copied(); |
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.
let mut input_iter = input[start_inx..].iter().copied(); | |
buf[..input.len()].copy_from_slice(&input[..]); |
It also needs a check above that the input length is <= 32.
let mut px_buf = [0u8; 32]; | ||
let mut py_buf = [0u8; 32]; | ||
let mut input_iter = input[start_inx..].iter().copied(); | ||
px_buf.fill_with(|| input_iter.next().unwrap_or(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.
Same as above, please use copy_with_slice
.
let mut mod_len_buf = [0u8; 32]; | ||
|
||
let mut input_iter = input.iter().copied(); | ||
base_len_buf.fill_with(|| input_iter.next().unwrap_or(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.
Also same as above, use copy_with_slice
.
if mod_len == 0 { | ||
return Ok(PrecompileOutput { | ||
exit_status: ExitSucceed::Returned, | ||
output: vec![], |
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.
Is this actually right? EIP-198 states:
returns an output (BASE**EXPONENT) % MODULUS as a byte array with the same length as the modulus.
So if I'm to understand the spec, this should be a number of zeros, instead of an empty array.
Also is this special case actually needed? L166 already has:
if base_len == 0 && mod_len == 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.
Base len is encoded before mod len, so a truncated input could have non-zero base len but zero mod len.
As the EIP states that it returns a byte array with the same length as the modulus, then if mod len is 0 the output should be zero len too.
I'm not too familiar with Go but this seems to return zero len array:
https://github.com/ethereum/go-ethereum/blob/v1.10.26/core/vm/contracts.go#L386
let base_start = 96; // previous 3 32-byte fields | ||
let base = BigUint::from_bytes_be(&input[base_start..base_start + base_len]); | ||
let mut base_buf = vec![0u8; base_len]; | ||
base_buf.fill_with(|| input_iter.next().unwrap_or(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.
Same as above, please use copy_with_slice
.
@sorpaas can we get an additional review from you? |
Precompiles modexp(5), ecadd(6) and ecmul(7) have inconsistencies compared to the yellowpaper and geth implementation.
&
operator in the EIP2565. The correct behavior, also expressed in the yellowpaper, is to take the first 32 bytes of the exp input, while in Rust(exponent & (2**256 - 1))
will keep the 32 last bytes. To avoid any confusion, I do like in the yellowpaper by looking directly at the first 32 bytes in the input, which is what is done in geth.