-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Port Polkadot implementation to Rust. #4102
base: master
Are you sure you want to change the base?
Port Polkadot implementation to Rust. #4102
Conversation
Great stuff @satoshiotomakan will take a look next week when he is back from PTO |
58cf478
to
c5f078a
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.
Thanks for opening the PR! First review iteration
NetworkId::POLKADOT => PolkadotCallEncoder::new(ctx), | ||
NetworkId::KUSAMA => KusamaCallEncoder::new(ctx), | ||
NetworkId::POLYMESH => PolymeshCallEncoder::new(ctx), |
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.
While porting chains to Rust, we try to improve overall experience and codebase. Otherwise there is no much need in the migration.
We should handle this on the Entry level. So there should be separate tw_polkadot
and tw_kusama
crates, where you can, for example, provide a &dyn TWPolkadotCallEncoder object to a signer, or something like that.
Or it will be even better to provide a dynamic object that returns call indices for the asked extrinsic.
Please also note that we started using Polkadot blockchain implementation for all Substrate chains. For example, you can sign a transaction for Polymesh even if it's not in registry.json
by using custom CustomCallIndices
. But for breaking compatibility, we should use default values if the custom indices are not set for Polkadot or Kusama.
I think there is no need to add tw_polymesh
chain, but rather add it to the registry.json
file, and we'll use CustomCallIndices
for every 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.
I was planning on splitting tw_polkadot
into per-chain crates later. For this PR I didn't want to make major structural changes to how the Rust vs C++ Polkadot backend worked.
For a lot of Substrate chains a single generic backend that allows CustomCallIndices
would be enough, since they might only need Balance/Staking support. But for chains like Polymesh we have other calls that are needed to make using Trust Wallet work for our users.
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 I split tw_polkadot
into 3 different chain impls (polkadot, kusama, polymesh) in this PR? Also we could have one generic Substrate chain crate that requires custom call indices to support chains that just need balance/staking support.
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 have started work on moving Polymesh support into its own coin (tw_polymesh
crate). Here is a draft PR for that: PolymeshAssociation#2
Right now it still uses the Polkadot
protobufs definition, but we might want to make a new protobuf for Polymesh.
Hi @Neopallium, is the PR ready for the next review iteration? |
I have some more changes (use |
19437b6
to
a6558a7
Compare
@satoshiotomakan Ready for the next review. |
Hi @Neopallium, thank you for letting me know! I'll review it next Monday, sorry for the delay |
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.
Hi @Neopallium, thanks for the previous changes, appreciate the effort!
Last review iteration
// Special case for batches. | ||
match msg { | ||
SigningVariant::balance_call(b) => { | ||
if let Some(batch) = self.encode_balance_batch_call(b)? { | ||
return Ok(batch); | ||
} | ||
}, | ||
SigningVariant::staking_call(s) => { | ||
if let Some(batch) = self.encode_staking_batch_call(s)? { | ||
return Ok(batch); | ||
} | ||
}, | ||
_ => (), | ||
} | ||
// non-batch calls. | ||
self.encoder.encode_call(msg) |
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 find these batch and non-batch procession suboptimal and difficult to understand.
The problem is that some calls are handled in CallEncoder
(eg BondAndNominate
), and later converted into separated Bond
and Nominate
, and then forwarded to a Substrate specific encoder.
However, developers need to keep in mind that in PolkadotCallEncoder
you should return an error if BondAndNominate
is passed. It's not obvious. Also encode_staking_batch_call
confuses by returning optional value.
Could you please refactor it by providing a single structure responsible for Proto -> RawOwned
conversion?
You can make it the way so tw_polymesh
and tw_kusama
can just reuse some functions of the function. Please take a look at Greenfield chain as an example:
https://github.com/trustwallet/wallet-core/blob/master/rust/chains/tw_greenfield/src/modules/tx_builder.rs
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 note that GenericBalances
and GenericStaking
look good to me
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 find these batch and non-batch procession suboptimal and difficult to understand.
That is because of how thePolkadot.proto
has special cases for batching. Batching should not be handled inside each pallet. On Substrate networks batching of calls is handled by theUtility
pallet and each network can have some differences in that pallet.
I have tried multiple times to handle those special case batching inside the pallet (Balance, Staking), but it make all other simple call cases more complex.
In the next PR for Polymesh I have use a more generic batching method that simplifies the call encoding a lot:
Call encoder:
https://github.com/PolymeshAssociation/wallet-core/blob/polymesh_rust_impl/rust/chains/tw_polymesh/src/call_encoder.rs
Polymesh.proto:
https://github.com/PolymeshAssociation/wallet-core/blob/polymesh_rust_impl/src/proto/Polymesh.proto
The same designed could be used for Polkadot, but changing the proto file would break frontend clients.
e5466fa
to
4c80040
Compare
Hi @Neopallium, please let me know once the PR is ready for the final review |
@satoshiotomakan The only items remaining is:
|
@satoshiotomakan I finished porting all the C++ tests to Rust. Only kept left one C++ signing test. Also added some Rust docs to |
Description
Continued the C++ -> Rust port of the Polkadot/Substrate blockchain from PR #3857.
Adds Rust crates:
tw_scale
- SCALE encoding.tw_ss58_address
- SS58 address.tw_substrate
- Common code for supporting Substrate chains. Substrate chains can implement theSubstrateCoinEntry
trait (see thetw_polkadot
crate) instead ofCoinEntry
.tw_polkadot
- Polkadot/Kusama blockchain.How to test
Types of changes
Checklist
If you're adding a new blockchain