-
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
Move Polkadot implementation to Rust #3857
Draft
doom
wants to merge
18
commits into
master
Choose a base branch
from
polkadot-rust
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
9a45566
Add the tw_ss58_address crate
doom c934b77
Apply suggestions from code review, refactor some utility functions
doom da1ad8b
Remove unused dependency
doom 59665b4
Add PolkadotAddress
doom 2d896db
Add NetworkId constants and Hash derivation
doom ae5f5db
Add SCALE encoding for integers (fixed and compact)
doom 6ea7c1e
Fix tiny things in scale.rs
doom be51123
Add extrinsics
doom a5bf37e
Add PolkadotPrefix
doom a6c5f85
Require a pre-built NetworkId when deriving SS58Address
doom 0937ed7
Format extrinsic.rs
doom adf5906
Add address parsing and derivation in entry.rs
doom 8943f6b
Rename SS58Address::from_str to SS58Address::parse
doom 2dbcf0b
Add SubstrateNetwork to AddressPrefix enum
doom 307fbf4
Rework ToScale trait to allow encoding to an existing Vec, add more i…
doom 136962d
Refactor Extrinsic to use in-place encoding
doom 33ff36c
Add more tests for staking extrinsics
doom efc475e
Introduce ExtrinsicEncoder helper to build encoded extrinsics
doom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "tw_polkadot" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
lazy_static = "1.4.0" | ||
tw_coin_entry = { path = "../../tw_coin_entry" } | ||
tw_encoding = { path = "../../tw_encoding" } | ||
tw_hash = { path = "../../tw_hash" } | ||
tw_keypair = { path = "../../tw_keypair" } | ||
tw_memory = { path = "../../tw_memory" } | ||
tw_number = { path = "../../tw_number" } | ||
tw_proto = { path = "../../tw_proto" } | ||
tw_ss58_address = { path = "../../tw_ss58_address" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
use std::fmt; | ||
use std::str::FromStr; | ||
use tw_coin_entry::coin_entry::CoinAddress; | ||
use tw_coin_entry::error::prelude::*; | ||
use tw_coin_entry::prefix::AddressPrefix; | ||
use tw_memory::Data; | ||
use tw_ss58_address::{NetworkId, SS58Address}; | ||
|
||
#[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
pub struct PolkadotPrefix(NetworkId); | ||
|
||
impl PolkadotPrefix { | ||
pub fn network(self) -> NetworkId { | ||
self.0 | ||
} | ||
} | ||
|
||
impl TryFrom<AddressPrefix> for PolkadotPrefix { | ||
type Error = AddressError; | ||
|
||
fn try_from(prefix: AddressPrefix) -> Result<Self, Self::Error> { | ||
match prefix { | ||
AddressPrefix::SubstrateNetwork(network) => NetworkId::from_u16(network).map(Self), | ||
_ => Err(AddressError::UnexpectedAddressPrefix), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
pub struct PolkadotAddress(pub SS58Address); | ||
|
||
impl PolkadotAddress { | ||
pub fn with_network_check(self) -> AddressResult<Self> { | ||
if self.0.network() != NetworkId::POLKADOT { | ||
return Err(AddressError::UnexpectedAddressPrefix); | ||
} | ||
Ok(self) | ||
} | ||
} | ||
|
||
impl CoinAddress for PolkadotAddress { | ||
#[inline] | ||
fn data(&self) -> Data { | ||
self.0.to_bytes() | ||
} | ||
} | ||
|
||
impl FromStr for PolkadotAddress { | ||
type Err = AddressError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
SS58Address::from_str(s).map(PolkadotAddress) | ||
} | ||
} | ||
|
||
impl fmt::Display for PolkadotAddress { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
fmt::Display::fmt(&self.0, f) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
use tw_coin_entry::coin_context::CoinContext; | ||
use tw_coin_entry::coin_entry::{PublicKeyBytes, SignatureBytes}; | ||
use tw_coin_entry::error::prelude::*; | ||
use tw_coin_entry::signing_output_error; | ||
use tw_proto::Polkadot::Proto; | ||
use tw_proto::TxCompiler::Proto as CompilerProto; | ||
|
||
pub struct PolkadotCompiler; | ||
|
||
impl PolkadotCompiler { | ||
#[inline] | ||
pub fn preimage_hashes( | ||
coin: &dyn CoinContext, | ||
input: Proto::SigningInput<'_>, | ||
) -> CompilerProto::PreSigningOutput<'static> { | ||
Self::preimage_hashes_impl(coin, input) | ||
.unwrap_or_else(|e| signing_output_error!(CompilerProto::PreSigningOutput, e)) | ||
} | ||
|
||
fn preimage_hashes_impl( | ||
_coin: &dyn CoinContext, | ||
_input: Proto::SigningInput<'_>, | ||
) -> SigningResult<CompilerProto::PreSigningOutput<'static>> { | ||
todo!() | ||
} | ||
|
||
#[inline] | ||
pub fn compile( | ||
coin: &dyn CoinContext, | ||
input: Proto::SigningInput<'_>, | ||
signatures: Vec<SignatureBytes>, | ||
public_keys: Vec<PublicKeyBytes>, | ||
) -> Proto::SigningOutput<'static> { | ||
Self::compile_impl(coin, input, signatures, public_keys) | ||
.unwrap_or_else(|e| signing_output_error!(Proto::SigningOutput, e)) | ||
} | ||
|
||
fn compile_impl( | ||
_coin: &dyn CoinContext, | ||
_input: Proto::SigningInput<'_>, | ||
_signatures: Vec<SignatureBytes>, | ||
_public_keys: Vec<PublicKeyBytes>, | ||
) -> SigningResult<Proto::SigningOutput<'static>> { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
use crate::address::{PolkadotAddress, PolkadotPrefix}; | ||
use crate::compiler::PolkadotCompiler; | ||
use crate::signer::PolkadotSigner; | ||
use std::str::FromStr; | ||
use tw_coin_entry::coin_context::CoinContext; | ||
use tw_coin_entry::coin_entry::{CoinEntry, PublicKeyBytes, SignatureBytes}; | ||
use tw_coin_entry::derivation::Derivation; | ||
use tw_coin_entry::error::prelude::*; | ||
use tw_coin_entry::modules::json_signer::NoJsonSigner; | ||
use tw_coin_entry::modules::message_signer::NoMessageSigner; | ||
use tw_coin_entry::modules::plan_builder::NoPlanBuilder; | ||
use tw_coin_entry::modules::transaction_decoder::NoTransactionDecoder; | ||
use tw_coin_entry::modules::wallet_connector::NoWalletConnector; | ||
use tw_keypair::tw::PublicKey; | ||
use tw_proto::Polkadot::Proto; | ||
use tw_proto::TxCompiler::Proto as CompilerProto; | ||
use tw_ss58_address::{NetworkId, SS58Address}; | ||
|
||
pub struct PolkadotEntry; | ||
|
||
impl CoinEntry for PolkadotEntry { | ||
type AddressPrefix = PolkadotPrefix; | ||
type Address = PolkadotAddress; | ||
type SigningInput<'a> = Proto::SigningInput<'a>; | ||
type SigningOutput = Proto::SigningOutput<'static>; | ||
type PreSigningOutput = CompilerProto::PreSigningOutput<'static>; | ||
|
||
// Optional modules: | ||
type JsonSigner = NoJsonSigner; | ||
type PlanBuilder = NoPlanBuilder; | ||
type MessageSigner = NoMessageSigner; | ||
type WalletConnector = NoWalletConnector; | ||
type TransactionDecoder = NoTransactionDecoder; | ||
|
||
#[inline] | ||
fn parse_address( | ||
&self, | ||
_coin: &dyn CoinContext, | ||
address: &str, | ||
_prefix: Option<Self::AddressPrefix>, | ||
) -> AddressResult<Self::Address> { | ||
PolkadotAddress::from_str(address)?.with_network_check() | ||
} | ||
|
||
#[inline] | ||
fn parse_address_unchecked( | ||
&self, | ||
_coin: &dyn CoinContext, | ||
address: &str, | ||
) -> AddressResult<Self::Address> { | ||
PolkadotAddress::from_str(address) | ||
} | ||
|
||
#[inline] | ||
fn derive_address( | ||
&self, | ||
_coin: &dyn CoinContext, | ||
public_key: PublicKey, | ||
_derivation: Derivation, | ||
prefix: Option<Self::AddressPrefix>, | ||
) -> AddressResult<Self::Address> { | ||
let public_key = public_key | ||
.to_ed25519() | ||
.ok_or(AddressError::PublicKeyTypeMismatch)?; | ||
|
||
SS58Address::from_public_key( | ||
public_key, | ||
prefix | ||
.map(PolkadotPrefix::network) | ||
.unwrap_or(NetworkId::POLKADOT), | ||
) | ||
.map(PolkadotAddress) | ||
} | ||
|
||
#[inline] | ||
fn sign(&self, coin: &dyn CoinContext, input: Self::SigningInput<'_>) -> Self::SigningOutput { | ||
PolkadotSigner::sign(coin, input) | ||
} | ||
|
||
#[inline] | ||
fn preimage_hashes( | ||
&self, | ||
coin: &dyn CoinContext, | ||
input: Self::SigningInput<'_>, | ||
) -> Self::PreSigningOutput { | ||
PolkadotCompiler::preimage_hashes(coin, input) | ||
} | ||
|
||
#[inline] | ||
fn compile( | ||
&self, | ||
coin: &dyn CoinContext, | ||
input: Self::SigningInput<'_>, | ||
signatures: Vec<SignatureBytes>, | ||
public_keys: Vec<PublicKeyBytes>, | ||
) -> Self::SigningOutput { | ||
PolkadotCompiler::compile(coin, input, signatures, public_keys) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
We should allow to verify Kusama, Acala and other addresses via the Polkadot implementation. To achieve this, it's worth to check the address prefix if it's provided and SS58