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

[master] v1 metamask connect to isolated server + testnet #2820

Merged
merged 75 commits into from
Jul 29, 2022

Conversation

n-hutton
Copy link
Contributor

@n-hutton n-hutton commented Jun 24, 2022

MVP getting metamask to connect to the testnet and move funds about.

TL;DR: by using the old zil api you can transfer to a metamask account. You can then transfer between these accounts. The mechanism for tracking mined TX is not yet in place so metamask thinks they are still pending:
Screenshot from 2022-07-14 10-43-22

This required adding a library for ECDSA public key recovery (that is, given a message and a signature, derive the public key), which was forked from bitcoin-core. I do not know how esteemed/well tested this library is. It was used by Aleth.

Details:

The main difficulty is getting the details of the raw transaction submission correct - it is detailed here: https://eips.ethereum.org/EIPS/eip-155

The current solution I think only works if metamask thinks your chain height is over 2,675,000 - otherwise, it would use a different signing scheme. The solution I go with might be the code just checks for both.

In order to add a raw eth transaction, you do the following:
Parse all the fields from the transaction using ethereum serialization format 'RLP'
Replace the signature with 0 and hash the transaction to determine the hash that was created client side
Put it back into RLP format and hash it
Use this hash to recreate the public key

There are some dummy values returned for the queries that metamask likes to see that need to be filled in - getting blocks by hash etc.

Note: get balance for eth returns a hex value, whereas zil returns a decimal string. So there is potential for massively incorrect balances to be shown if it is not used correctly.

Adds the following API calls:

eth_blockNumber
net_version
eth_getBalance
eth_getBlockByNumber
eth_gasPrice
eth_getCode
eth_estimateGas
eth_getTransactionCount
eth_sendRawTransaction
eth_getTransactionReceipt - needs to be added to lookup server (!)

@github-actions github-actions bot changed the title v1 metamask connect - try testnet, too [master] v1 metamask connect - try testnet, too Jun 24, 2022
@n-hutton n-hutton marked this pull request as ready for review July 21, 2022 11:03
constants.xml Outdated Show resolved Hide resolved
constants.xml Outdated Show resolved Hide resolved
constants.xml Outdated Show resolved Hide resolved
@@ -792,6 +847,187 @@ Json::Value LookupServer::CreateTransaction(
}
}

Json::Value LookupServer::CreateTransactionEth(EthFields const& fields, bytes const& pubKey, const unsigned int num_shards,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it neccassary to have this code in both isolated server and lookup server, could it not be common to both? just asking :-) or is this just temporary ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the code that can be common is common - so the isolated server calls the lookup server's implementation when it is simple (like getting the chain id)

Copy link
Contributor

@Steve-White-UK Steve-White-UK left a comment

Choose a reason for hiding this comment

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

Fairly understandble, just a couple of comments will seek clarification tommorw.

@codecov-commenter
Copy link

codecov-commenter commented Jul 23, 2022

Codecov Report

Merging #2820 (109df60) into master (2316603) will increase coverage by 0.55%.
The diff coverage is 60.27%.

@@            Coverage Diff             @@
##           master    #2820      +/-   ##
==========================================
+ Coverage   32.76%   33.32%   +0.55%     
==========================================
  Files         274      278       +4     
  Lines       42694    43231     +537     
==========================================
+ Hits        13987    14405     +418     
- Misses      28707    28826     +119     
Impacted Files Coverage Δ
src/common/Constants.h 100.00% <ø> (ø)
src/libData/AccountData/Transaction.cpp 75.86% <0.00%> (-2.71%) ⬇️
src/libData/AccountData/Transaction.h 100.00% <ø> (ø)
src/libNode/DSBlockProcessing.cpp 0.00% <ø> (ø)
src/libValidator/Validator.cpp 2.76% <0.00%> (+<0.01%) ⬆️
src/libServer/LookupServer.cpp 18.26% <21.16%> (+2.19%) ⬆️
src/libCrypto/EthCrypto.cpp 28.46% <50.00%> (+28.46%) ⬆️
src/libUtils/DataConversion.cpp 44.11% <61.11%> (-8.02%) ⬇️
src/libServer/LookupServer.h 32.71% <63.15%> (+9.32%) ⬆️
src/libEth/Eth.cpp 76.92% <76.92%> (ø)
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2316603...109df60. Read the comment docs.

@n-hutton n-hutton requested review from bzawisto and art-gor July 26, 2022 13:40
Copy link
Contributor

@bzawisto bzawisto left a comment

Choose a reason for hiding this comment

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

Well done Nathan! There are a couple of nitpick comments so if you don't want to address them that's still fine!

src/libCrypto/EthCrypto.cpp Outdated Show resolved Hide resolved
src/libCrypto/EthCrypto.cpp Outdated Show resolved Hide resolved
src/libCrypto/EthCrypto.cpp Outdated Show resolved Hide resolved
src/libCrypto/EthCrypto.cpp Outdated Show resolved Hide resolved
src/libData/AccountData/Transaction.cpp Outdated Show resolved Hide resolved
@@ -491,6 +549,166 @@ Json::Value IsolatedServer::CreateTransaction(const Json::Value& _json) {
}
}

Json::Value IsolatedServer::CreateTransactionEth(EthFields const& fields,
Copy link
Contributor

Choose a reason for hiding this comment

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

Presumably challenging, but do you think it's feasible to split this function into smaller entities (now it's > 150 loc).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, I can do this - I was basically copying the code from the scilla way of adding TX so can refactor both in a seperate PR if you like?

@@ -49,6 +50,24 @@ class IsolatedServer : public LookupServer,
response = this->CreateTransaction(request[0u]);
}

inline virtual void GetEthSendRawTransactionI(const Json::Value& request,
Json::Value& response) {
(void)request;
Copy link
Contributor

Choose a reason for hiding this comment

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

If we don't use request, should we enclose it with / * */ in the arg list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh. Request is used. The (void) was a copy/paste error in this instance. I don't mind refactoring to use /* */ instead of a void cast in a future PR if you like?

rawTx.erase(0, 2);
}

auto pubKey = RecoverECDSAPubSig(rawTx, ETH_CHAINID_INT);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: immutable vars could be marked as const.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

}

// Given a RLP message, parse out the fields and return a EthFields object
EthFields parseRawTxFields(std::string const& message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit of a subtle piece of code, can we write some unit test just to have a mean of checking if it still works in case someone wants to change it one day?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds great - done

// is in line with EIP-155.
// message shall not contain '0x'
bytes RecoverECDSAPubSig(std::string const& message, int chain_id) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be nice to have a unit test for some predefined input and known output (just to ensure it works in case someone needs to change it).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds great - done

@n-hutton n-hutton merged commit 50441f1 into master Jul 29, 2022
@n-hutton n-hutton deleted the feature/evm_rpc branch July 29, 2022 11:00
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.

4 participants