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

implement eth_call state override #1027

Conversation

nbaztec
Copy link
Contributor

@nbaztec nbaztec commented Mar 21, 2023

Implements call state override for eth_call as an optional parameter to be passed to override the state. Similar to geth.

@nbaztec nbaztec requested a review from sorpaas as a code owner March 21, 2023 11:59
@sorpaas
Copy link
Member

sorpaas commented Mar 23, 2023

Tests fail.

@nbaztec
Copy link
Contributor Author

nbaztec commented Mar 23, 2023

Tests fail.

Odd I cannot seem to reproduce that failure locally. I tried several times:

$ cd template/node
$ cargo build --release --locked --verbose --features rpc-binary-search-estimate
...
$ cd ts-tests
$ npm test

and it is consistently passing.

Is there anything else that might involve the template node being built differently?

The test that fails is:

1) Frontier RPC (StateOverride)
       should have a sender balance of 150 with state override:

which pertains to the storage override for System.Account pallet via runtime_storage_override in EthDeps, so my guess would be that something doesn't work there effectively, but I can't see why as it's working locally just fine.

EDIT: Seems for some reason the address mapping on CI is IdentityAddressMapping but locally I get HashedAddressMapping

Copy link
Member

@sorpaas sorpaas left a comment

Choose a reason for hiding this comment

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

I see you already figured out the CI issue -- you probably didn't delete the old local runtime folder.

@@ -39,6 +40,28 @@ pub struct TransactionStatus {
pub logs_bloom: Bloom,
}

pub trait EvmRuntimeAddressMapping {
Copy link
Member

Choose a reason for hiding this comment

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

Evm should be all capitalized EVM as it is elsewhere. Alternatively, you can also just name it RuntimeAddressMapping since the EVM part is non-ambiguous. Same for the trait below.

In addition, make this trait non-implementable by having a generic impl, because we already have the AddressMapping trait.

impl<T: AsRef<[u8]>, U: pallet_evm::AddressMapping<T>> RuntimeAddressMapping for U {
  fn into_account_id_bytes(address: H160) -> Vec<u8> {
    U::into_account_id(address).as_ref().to_vec()
  }
}

You can probably also just reuse AddressMapping<Vec<u8>>, but I'm not sure if there's specialization issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I thought about using AddressMapping<Vec<u8>> but since there's an impl impl<T: From<H160>> already in causes ambiguous implementation since From<H160> can implemented for Vec<u8> as well. It could be solved by adding the fn into_account_id_bytes to the trait AddressMapping and may be reused while computing the account_id

impl<H: Hasher<Out = H256>> AddressMapping<AccountId32> for HashedAddressMapping<H> {
	fn into_account_id(address: H160) -> AccountId32 {
		AccountId32::from_slice(&Self::into_account_id_bytes(address));
	}

	fn into_account_id_bytes(address: H160) -> Vec<u8> {
		let mut data = [0u8; 24];
		data[0..4].copy_from_slice(b"evm:");
		data[4..24].copy_from_slice(&address[..]);
		let hash = H::hash(&data);

		Into::<[u8; 32]>::into(hash).to_owned()

	}
}

thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

If you can make into_account_id_bytes a default impl, then it should work. However, this will require adding AsRef<[u8]> constraint to T, which I think is okay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems in the pallet-evm Config we pass AccountId to AddressMapping which doesn't have the AsRef<[u8]> trait bound


use crate::{
eth::{rich_block_build, Eth},
frontier_backend_client, internal_err,
};

impl<B, C, P, CT, BE, H: ExHashT, A: ChainApi, EGA> Eth<B, C, P, CT, BE, H, A, EGA>
impl<B, C, P, CT, BE, H: ExHashT, A: ChainApi, M: EvmRuntimeAddressMapping, EGA>
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 the time we should group EGA together with M into an RPC config trait (because they can not be implied).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you perhaps elaborate how this trait might look like?

Copy link
Member

Choose a reason for hiding this comment

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

Basically this old PR #736

We didn't went with all the type parameters because most of them can be inferred by the compiler. In the past we only had a single one EGA which belongs to Config. The new type parameter we have in this PR also belongs to Config.

Something like this:

trait EthConfig {
   type EstimateGasAdapter;
   type RuntimeAddressMapping;
}

Then in Eth put the type parameter Config: EthConfig.

@nbaztec
Copy link
Contributor Author

nbaztec commented Mar 31, 2023

@sorpaas could you please take a look if this is good now? Thanks.

impl<B: BlockT, C, P, CT, BE, H: ExHashT, A: ChainApi, EC: EthConfig<B, C>>
Eth<B, C, P, CT, BE, H, A, EC>
{
pub fn with_eth_config<EC2: EthConfig<B, C>>(self) -> Eth<B, C, P, CT, BE, H, A, EC2> {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub fn with_eth_config<EC2: EthConfig<B, C>>(self) -> Eth<B, C, P, CT, BE, H, A, EC2> {
pub fn replace_config<EC2: EthConfig<B, C>>(self) -> Eth<B, C, P, CT, BE, H, A, EC2> {

with_eth_config sounds like a constructor, which this isn't. Our previous with_estimate_gas_adapter had the same problem.

fn into_account_id_bytes(address: H160) -> Vec<u8>;
}

impl<B: BlockT, C> RuntimeStorageOverride<B, C> for () {
Copy link
Member

Choose a reason for hiding this comment

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

Remove this and the () impl for EthConfig?

Or alternatively, make this "no-op" set_overlay_changes. into_account_id_bytes should be able to have a default impl for AsRef<[u8]>. This may be preferred as it impact existing users who don't care about overlay changes the least.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah we could go with no-op the is_enabled can stay false to signal an incoming call with balance and nonce overrides with an error that it's unsupported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

into_account_id_bytes is tightly coupled with RuntimeStorageOverride now so it should be sufficient to return the default value within the () impl.

@nbaztec nbaztec requested a review from sorpaas April 4, 2023 13:52
@sorpaas sorpaas merged commit 2b09a67 into polkadot-evm:master Apr 11, 2023
CertainLach pushed a commit to UniqueNetwork/unique-frontier that referenced this pull request Apr 13, 2023
* make call_api_at work

* make override work

* implement default storage override

* use address indexed stateOverrides

* allow overriding state in eth_call

* add tests

* resolve conflicts

* use explicit param

* use concrete type in EthDeps

* fix merge conflicts

* format toml

* try-debug failure

* debug test

* change value for AddressMapping

* remove debug

* fmt

* fix build

* fix build

* name refactor

* attempt simplifying rpc Eth traits

* rename default implementations

* cleanup

* lint

* bump

* fmt

* fix clippy

* make default implementation no-op

* fix build
ashutoshvarma pushed a commit to AstarNetwork/frontier that referenced this pull request May 29, 2023
* make call_api_at work

* make override work

* implement default storage override

* use address indexed stateOverrides

* allow overriding state in eth_call

* add tests

* resolve conflicts

* use explicit param

* use concrete type in EthDeps

* fix merge conflicts

* format toml

* try-debug failure

* debug test

* change value for AddressMapping

* remove debug

* fmt

* fix build

* fix build

* name refactor

* attempt simplifying rpc Eth traits

* rename default implementations

* cleanup

* lint

* bump

* fmt

* fix clippy

* make default implementation no-op

* fix build
ashutoshvarma pushed a commit to AstarNetwork/frontier that referenced this pull request Jun 8, 2023
* make call_api_at work

* make override work

* implement default storage override

* use address indexed stateOverrides

* allow overriding state in eth_call

* add tests

* resolve conflicts

* use explicit param

* use concrete type in EthDeps

* fix merge conflicts

* format toml

* try-debug failure

* debug test

* change value for AddressMapping

* remove debug

* fmt

* fix build

* fix build

* name refactor

* attempt simplifying rpc Eth traits

* rename default implementations

* cleanup

* lint

* bump

* fmt

* fix clippy

* make default implementation no-op

* fix build
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.

2 participants