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

Contract mock system #583

Merged
merged 21 commits into from
Aug 16, 2021
Merged

Contract mock system #583

merged 21 commits into from
Aug 16, 2021

Conversation

taminomara
Copy link
Contributor

Fix #83.

Implement mock system for contracts. Currently mimicking mockall interface.

See the attached issue for more details and discussion.

@taminomara taminomara requested a review from a team July 13, 2021 10:15
@taminomara
Copy link
Contributor Author

This is a work in progress PR. I'll be updating it from time to time, although I'm focusing on other issues for now. You're welcome to comment on it (see also #83), but bear in mind that this code is far from its final state, and I expect it be changed quite a lot.

ethcontract/src/mock.rs Outdated Show resolved Hide resolved
@taminomara taminomara force-pushed the ethcontract-rs-83 branch 3 times, most recently from 1ec8642 to 997ef38 Compare July 26, 2021 14:20
@taminomara
Copy link
Contributor Author

This is still WIP, but the version with a simple callback for each contract method works (see test).

Copy link
Contributor

@fleupold fleupold left a comment

Choose a reason for hiding this comment

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

Looks very promising!


state.block += 1;

let receipt = TransactionReceipt {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if it's a good idea to leave most values empty here. Maybe we should check how a "normal" tx receipt looks like and use default hash values instead of None values?

ethcontract-mock/src/lib.rs Outdated Show resolved Hide resolved
ethcontract-mock/src/parse.rs Outdated Show resolved Hide resolved
}

// Unwraps `Result`, adds info with current arg index and rpc name.
fn res<T, E: Display>(&self, res: Result<T, E>) -> T {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: maybe more descriptive name?

ethcontract-mock/src/test.rs Outdated Show resolved Hide resolved
ethcontract-mock/src/details.rs Outdated Show resolved Hide resolved
@taminomara taminomara marked this pull request as ready for review July 28, 2021 15:20
@taminomara
Copy link
Contributor Author

I'll add docs and tests later today. The code is ready for review!

Copy link
Contributor

@nlordell nlordell left a comment

Choose a reason for hiding this comment

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

Finally! Mocked contracts!

As a general comment this PR was very large and quite difficult to review. It would have been nice to have been split into smaller pieces that could be merged (even if they were effectively dead code for a few commits) just to make the review process easier.

/// [`method`]: `Instance::method`
/// [`view_method`]: `Instance::view_method`
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct Signature<P, R>(pub H32, pub std::marker::PhantomData<(P, R)>);
Copy link
Contributor

Choose a reason for hiding this comment

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

Love it.

receipts: HashMap<H256, TransactionReceipt>,
}

impl MockTransport {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wow! You implemented a mock transport that handles all the ethcontract necessary RPC calls!

One thing that I worry about is that we may make use of additional RPC methods in ethcontract and forget to add them here. I can't think of a good way to deal with this though.

// We could support signing if user adds accounts with their private
// keys during mock setup.

panic!("mock node can't sign transactions, use offline signing with private key");
Copy link
Contributor

Choose a reason for hiding this comment

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

We can just sign with PrivateKey::ONE in these cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have to sign with private key for the from address, unfortunately. Otherwise transaction hash will be botched and something might break.

Copy link
Contributor

Choose a reason for hiding this comment

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

If from is None we can still use PrivateKey::ONE 😄.

panic!("mock node does not support executing methods on earliest block");
}
BlockNumber::Number(n) if n.as_u64() != state.block => {
panic!("mock node does not support executing methods on non-last block");
Copy link
Contributor

Choose a reason for hiding this comment

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

This is something we likely need for GPv2 services. However, seeing as the PR is already quite large, we can leave it for later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In hopes of avoiding this issue for as long as possible we allow specific block number if it's equal to the current top block number. But you're right, we'll have to support this eventually.

ethcontract-mock/src/details/mod.rs Outdated Show resolved Hide resolved
let mut state = self.state.lock().unwrap();
let expectation = state.expectation::<P, R>(address, signature, index, generation);
expectation.returns = Returns::Default;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Might also be worth adding a mine function to increment the block number.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also something for another PR (as this one is already quite large).

);
self
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Very nice documentation.

/// [`expect`]: Contract::expect
pub fn checkpoint(&self) {
self.transport.checkpoint();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

similar comment about a mine method.

Copy link
Contributor

@vkgnosis vkgnosis left a comment

Choose a reason for hiding this comment

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

Nice.

ethcontract-mock/src/details/mod.rs Outdated Show resolved Hide resolved
ethcontract-mock/src/details/mod.rs Outdated Show resolved Hide resolved
ethcontract-mock/src/details/parse.rs Show resolved Hide resolved
@taminomara
Copy link
Contributor Author

As a general comment this PR was very large and quite difficult to review.

Sorry about that, I should've made smaller PRs throughout the development process.

Copy link
Contributor

@bh2smith bh2smith left a comment

Choose a reason for hiding this comment

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

All of this looks really great although some of it is a bit beyond me to see how so many different things connect. Perhaps smaller incremental changes would have helped focus on some of the more abstract concepts. I will continue to read and review, but it is looking pretty good overall.

ethcontract-mock/src/details/default.rs Show resolved Hide resolved
@taminomara
Copy link
Contributor Author

I want to merge and release this PR today. I'll merge it without squashing to preserve commit history. I've also made an interactive rebase to account for web3 update that has happened in main.

@taminomara taminomara merged commit e59df9d into main Aug 16, 2021
@taminomara taminomara deleted the ethcontract-rs-83 branch August 16, 2021 08:50
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.

Generate a Mocked Version of the Contract.
5 participants