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

Port Polkadot implementation to Rust. #4102

Open
wants to merge 105 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 96 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
13c2d5d
Add the tw_ss58_address crate
doom May 27, 2024
0c5b2dc
Apply suggestions from code review, refactor some utility functions
doom May 27, 2024
59f1894
Remove unused dependency
doom May 27, 2024
70775c0
Add PolkadotAddress
doom May 28, 2024
2a6a0fa
Add NetworkId constants and Hash derivation
doom May 28, 2024
fbc9bff
Add SCALE encoding for integers (fixed and compact)
doom May 29, 2024
c09f789
Fix tiny things in scale.rs
doom May 31, 2024
3d41165
Add extrinsics
doom May 31, 2024
a56fb70
Add PolkadotPrefix
doom May 31, 2024
54b4a7e
Require a pre-built NetworkId when deriving SS58Address
doom May 31, 2024
13b67d1
Format extrinsic.rs
doom May 31, 2024
ea6d34f
Add address parsing and derivation in entry.rs
doom May 31, 2024
dc8565f
Rename SS58Address::from_str to SS58Address::parse
doom May 31, 2024
956b5f8
Add SubstrateNetwork to AddressPrefix enum
doom May 31, 2024
2c22292
Rework ToScale trait to allow encoding to an existing Vec, add more i…
doom Jun 2, 2024
0f3e40e
Refactor Extrinsic to use in-place encoding
doom Jun 2, 2024
2ab4ff0
Add more tests for staking extrinsics
doom Jun 3, 2024
0988d21
Introduce ExtrinsicEncoder helper to build encoded extrinsics
doom Jun 3, 2024
ba3b6da
Refactor Scale encoding into tw_scale crate.
Neopallium Aug 19, 2024
fd2c5de
Add u128 SCALE support.
Neopallium Aug 21, 2024
a27cd1b
Fix: Use correct endianess.
Neopallium Aug 21, 2024
e08adb9
Add struct/enum SCALE encoding macros.
Neopallium Sep 17, 2024
5c74916
Add Substrate ExtrinsicV4 encoding.
Neopallium Sep 17, 2024
0f2a63a
U256 to u128.
Neopallium Sep 19, 2024
65562a9
Add Substrate call encoding support.
Neopallium Sep 19, 2024
624bdc6
Fix some incorrect tests.
Neopallium Sep 20, 2024
5032fb8
Add more extrinsic support.
Neopallium Sep 20, 2024
732fff4
Fix Option SCALE encoding.
Neopallium Sep 20, 2024
e327cc1
Add Polymesh network id.
Neopallium Sep 20, 2024
90aeca7
Remove extra lifetimes. Simplify code.
Neopallium Oct 4, 2024
09ccc91
More encoder refactoring.
Neopallium Oct 4, 2024
c4160de
Fix SCALE encoding test for Option type.
Neopallium Nov 1, 2024
ee7bd86
Update Polkadot CoinEntry impl.
Neopallium Nov 1, 2024
e2b56a2
Add support for custom call index.
Neopallium Nov 1, 2024
642348d
Implement Era SCALE encoding.
Neopallium Nov 4, 2024
388ecc5
cargo fmt
Neopallium Nov 4, 2024
15016e8
Move common Substrate logic in tw_substrate crate.
Neopallium Nov 4, 2024
db84e16
Improve bool SCALE code.
Neopallium Nov 4, 2024
1df2344
Refactor highly nested test code.
Neopallium Nov 4, 2024
b173034
cargo fmt
Neopallium Nov 4, 2024
8b0958c
Implment Polkadot coin address derivation test.
Neopallium Nov 4, 2024
284d1fd
Add more Era tests ported from the C++ tests.
Neopallium Nov 4, 2024
acce0ba
Refactor call encoder.
Neopallium Nov 4, 2024
e1bedb0
FIXUP
Neopallium Nov 4, 2024
c9a0433
Implement signer and compiler.
Neopallium Nov 5, 2024
a584ce6
Start adding tw_tests for polkadot.
Neopallium Nov 5, 2024
31e37d0
Add ss58prefix support to tw_coin_registry.
Neopallium Nov 5, 2024
a294f86
implement tw_any_address_is_valid_ss58 and tw_any_address_create_ss58…
Neopallium Nov 6, 2024
ba123dc
Fix missing length prefix when encoding signed transaction.
Neopallium Nov 6, 2024
e03bea1
cargo fmt
Neopallium Nov 6, 2024
8d3215e
Add support for CheckMetadata transaction extension.
Neopallium Nov 6, 2024
9ee77ee
Refactor transaction building.
Neopallium Nov 7, 2024
eb46135
Add support for optional MultiAddress.
Neopallium Nov 7, 2024
47c6216
Finish support for optional MultiAddress.
Neopallium Nov 7, 2024
6b25731
Fix C++ test, Rust impl returns different error code.
Neopallium Nov 7, 2024
b557119
Fix 'tip' support.
Neopallium Nov 7, 2024
dbe0238
Add support for ChargeAssetTxPayment (paying tx fee with asset).
Neopallium Nov 7, 2024
91a6b97
Remove unused call indices.
Neopallium Nov 7, 2024
7f5bd87
Add more SS58 address types.
Neopallium Nov 7, 2024
b2f1c4e
Update Polkadot C++ tests to use TWAny* interfaces.
Neopallium Nov 7, 2024
290d453
Use default value for block hashes.
Neopallium Nov 7, 2024
f77e784
Improve errors.
Neopallium Nov 7, 2024
b11b3a9
Support custom call indices in Polymesh.
Neopallium Nov 7, 2024
99c4b2c
Fix Polkadot CheckMetadataHash support
Neopallium Nov 7, 2024
cf9457c
Support old staking.bond calls.
Neopallium Nov 7, 2024
c76204b
Support Kusama with Rust impl. Remove old C++ impl.
Neopallium Nov 7, 2024
2f44bf0
Fix address derivation test for Acala and Kusama
Neopallium Nov 8, 2024
8118fab
Add Rust polkadot compile/sign tests.
Neopallium Nov 8, 2024
14317c4
cargo fmt
Neopallium Nov 8, 2024
58157ca
Merge TransactionBuilder and PrepareTransaction types.
Neopallium Nov 8, 2024
cc57666
Use SubstrateCoinEntry trait to better support Substrate chains.
Neopallium Nov 8, 2024
1da30d9
Add missing crates to top-level Cargo.toml.
Neopallium Nov 8, 2024
a9d584d
Re-enable test.
Neopallium Nov 8, 2024
ae672d2
Fix memory leaks in C++ unit tests.
Neopallium Nov 12, 2024
b09e9ff
Update Acala support to match C++.
Neopallium Nov 14, 2024
47874ba
Move tw_substrate to frameworks.
Neopallium Nov 21, 2024
456f2d5
Improve error reporting.
Neopallium Nov 21, 2024
009a7b7
Simplify Compact encoding.
Neopallium Nov 21, 2024
f08b80f
Refactor some rarely used SCALE code.
Neopallium Nov 21, 2024
142f1b1
Rename Encoded to RawOwned and move to tw_scale.
Neopallium Nov 21, 2024
c4c1160
Use H256 in Memo and IdentityId.
Neopallium Nov 21, 2024
2679356
Don't store KeyPair.
Neopallium Nov 21, 2024
b2342e8
Remove unused error variant.
Neopallium Nov 21, 2024
8d86d8d
Improve errors.
Neopallium Nov 21, 2024
537b2c9
Improve errors with context.
Neopallium Nov 27, 2024
d8566cf
Remove TWSS58AddressType
Neopallium Nov 27, 2024
2db5082
Remove deadcode
Neopallium Nov 27, 2024
ef638d5
Remove consts from tw_ss58_address crate.
Neopallium Nov 27, 2024
3bcac4c
Simplify impl_enum_scale macro
Neopallium Nov 27, 2024
3786896
Document SCALE macros.
Neopallium Nov 27, 2024
eb1587a
Some code cleanup and deps reorder.
Neopallium Dec 12, 2024
11e5bdc
Cleanup `parse_address`
Neopallium Dec 12, 2024
0f0592f
Fix RewardDestination. Added missing ACCOUNT variant.
Neopallium Dec 12, 2024
8217664
Remove assert.
Neopallium Dec 12, 2024
18a606f
Fix C++ tests and use original expected output.
Neopallium Dec 12, 2024
4c80040
Fix TODO
Neopallium Dec 12, 2024
083c345
Revert RewardDestination::ACCOUNT change.
Neopallium Dec 13, 2024
46862b9
Add links for Polymesh encoded transactions.
Neopallium Dec 13, 2024
7ea51a0
Cleanup error conversion code.
Neopallium Dec 13, 2024
82fe12a
Port some tests from C++ to Rust.
Neopallium Dec 16, 2024
3b42dc3
Finish porting C++ test to Rust.
Neopallium Dec 16, 2024
5ce8dbd
Remove old C++ tests. Only keep one for integration.
Neopallium Dec 16, 2024
7f18b1a
Sort crates.
Neopallium Dec 16, 2024
1ed06bc
Add docs to `tw_substrate`.
Neopallium Dec 16, 2024
b655581
More docs.
Neopallium Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions include/TrustWalletCore/TWSS58AddressType.h

This file was deleted.

53 changes: 53 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"chains/tw_aptos",
"chains/tw_binance",
Expand All @@ -11,13 +12,15 @@ members = [
"chains/tw_native_evmos",
"chains/tw_native_injective",
"chains/tw_pactus",
"chains/tw_polkadot",
"chains/tw_ronin",
"chains/tw_solana",
"chains/tw_sui",
"chains/tw_thorchain",
"chains/tw_ton",
"frameworks/tw_ton_sdk",
"frameworks/tw_utxo",
"frameworks/tw_substrate",
"tw_any_coin",
"tw_base58_address",
"tw_bech32_address",
Expand All @@ -35,6 +38,8 @@ members = [
"tw_tests",
"wallet_core_bin",
"wallet_core_rs",
"tw_scale",
"tw_ss58_address",
]

[profile.release]
Expand Down
16 changes: 16 additions & 0 deletions rust/chains/tw_polkadot/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "tw_polkadot"
version = "0.1.0"
edition = "2021"

[dependencies]
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_scale = { path = "../../tw_scale" }
tw_ss58_address = { path = "../../tw_ss58_address" }
tw_substrate = { path = "../../frameworks/tw_substrate" }
244 changes: 244 additions & 0 deletions rust/chains/tw_polkadot/src/call_encoder/generic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
use std::str::FromStr;

use tw_number::U256;
use tw_proto::Polkadot::Proto::{
mod_Balance::{AssetTransfer, OneOfmessage_oneof as BalanceVariant, Transfer},
mod_Staking::{
Bond, BondExtra, Chill, Nominate, OneOfmessage_oneof as StakingVariant, Rebond, Unbond,
WithdrawUnbonded,
},
Balance, RewardDestination as TWRewardDestination, Staking,
};
use tw_scale::{impl_enum_scale, Compact, RawOwned, ToScale};
use tw_ss58_address::SS58Address;
use tw_substrate::*;

use super::{required_call_index, validate_call_index};

impl_enum_scale!(
#[derive(Clone, Debug)]
pub enum GenericBalances {
TransferAllowDeath {
dest: MultiAddress,
value: Compact<u128>,
} = 0x00,
AssetTransfer {
id: Compact<u32>,
target: MultiAddress,
amount: Compact<u128>,
} = 0x05,
}
);

impl GenericBalances {
fn encode_transfer(ctx: &SubstrateContext, t: &Transfer) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&t.call_indices)?;
let address =
SS58Address::from_str(&t.to_address).map_err(|_| EncodeError::InvalidAddress)?;
let value = U256::from_big_endian_slice(&t.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

Ok(ci.wrap(Self::TransferAllowDeath {
dest: ctx.multi_address(address.into()),
value: Compact(value),
}))
}

fn encode_asset_transfer(
ctx: &SubstrateContext,
t: &AssetTransfer,
) -> WithCallIndexResult<Self> {
let ci = required_call_index(&t.call_indices)?;
let address =
SS58Address::from_str(&t.to_address).map_err(|_| EncodeError::InvalidAddress)?;
let amount = U256::from_big_endian_slice(&t.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

let asset_id = t.asset_id;
if asset_id > 0 {
Ok(ci.wrap(Self::AssetTransfer {
id: Compact(asset_id),
target: ctx.multi_address(address.into()),
amount: Compact(amount),
}))
} else {
Ok(ci.wrap(Self::TransferAllowDeath {
dest: ctx.multi_address(address.into()),
value: Compact(amount),
}))
}
}

pub fn encode_call(ctx: &SubstrateContext, b: &Balance) -> WithCallIndexResult<Self> {
match &b.message_oneof {
BalanceVariant::transfer(t) => Self::encode_transfer(ctx, t),
BalanceVariant::asset_transfer(t) => Self::encode_asset_transfer(ctx, t),
_ => EncodeError::NotSupported.tw_result(
"Unsupported batched balance variants here (maybe nested batch calls?)".to_string(),
),
}
}
}

impl_enum_scale!(
#[derive(Clone, Debug)]
pub enum RewardDestination {
Staked = 0x00,
Stash = 0x01,
Controller = 0x02,
Account(AccountId) = 0x03,
None = 0x04,
}
);

impl RewardDestination {
pub fn from_tw(dest: &TWRewardDestination, account: &str) -> EncodeResult<Self> {
match dest {
TWRewardDestination::STAKED => Ok(Self::Staked),
TWRewardDestination::STASH => Ok(Self::Stash),
TWRewardDestination::CONTROLLER => Ok(Self::Controller),
TWRewardDestination::ACCOUNT => {
let account =
SS58Address::from_str(account).map_err(|_| EncodeError::InvalidAddress)?;
Ok(Self::Account(SubstrateAddress(account)))
},
}
}
}

#[derive(Clone, Debug)]
pub struct BondCall {
controller: Option<MultiAddress>,
value: Compact<u128>,
reward: RewardDestination,
}

impl ToScale for BondCall {
fn to_scale_into(&self, out: &mut Vec<u8>) {
if let Some(controller) = &self.controller {
controller.to_scale_into(out);
}
self.value.to_scale_into(out);
self.reward.to_scale_into(out);
}
}

impl_enum_scale!(
#[derive(Clone, Debug)]
pub enum GenericStaking {
Bond(BondCall) = 0x00,
BondExtra { max_additional: Compact<u128> } = 0x01,
Unbond { value: Compact<u128> } = 0x02,
WithdrawUnbonded { num_slashing_spans: u32 } = 0x03,
Nominate { targets: Vec<MultiAddress> } = 0x05,
Chill = 0x06,
Rebond { value: Compact<u128> } = 0x13,
}
);

impl GenericStaking {
fn encode_bond(ctx: &SubstrateContext, b: &Bond) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
let controller = SS58Address::from_str(&b.controller)
.map(|addr| ctx.multi_address(addr.into()))
.ok();
let value = U256::from_big_endian_slice(&b.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

Ok(ci.wrap(Self::Bond(BondCall {
controller,
value: Compact(value),
reward: RewardDestination::from_tw(&b.reward_destination, &b.controller)?,
})))
}

fn encode_bond_extra(b: &BondExtra) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
let value = U256::from_big_endian_slice(&b.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

Ok(ci.wrap(Self::BondExtra {
max_additional: Compact(value),
}))
}

fn encode_chill(c: &Chill) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&c.call_indices)?;
Ok(ci.wrap(Self::Chill))
}

fn encode_unbond(b: &Unbond) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
let value = U256::from_big_endian_slice(&b.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

Ok(ci.wrap(Self::Unbond {
value: Compact(value),
}))
}

fn encode_rebond(b: &Rebond) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
let value = U256::from_big_endian_slice(&b.value)
.map_err(|_| EncodeError::InvalidValue)?
.try_into()
.map_err(|_| EncodeError::InvalidValue)?;

Ok(ci.wrap(Self::Rebond {
value: Compact(value),
}))
}

fn encode_withdraw_unbonded(b: &WithdrawUnbonded) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
Ok(ci.wrap(Self::WithdrawUnbonded {
num_slashing_spans: b.slashing_spans as u32,
}))
}

fn encode_nominate(ctx: &SubstrateContext, b: &Nominate) -> WithCallIndexResult<Self> {
let ci = validate_call_index(&b.call_indices)?;
let targets = b
.nominators
.iter()
.map(|target| {
let account =
SS58Address::from_str(&target).map_err(|_| EncodeError::InvalidAddress)?;
Ok(ctx.multi_address(account.into()))
})
.collect::<EncodeResult<Vec<MultiAddress>>>()?;
Ok(ci.wrap(Self::Nominate { targets }))
}

pub fn encode_call(ctx: &SubstrateContext, s: &Staking) -> WithCallIndexResult<Self> {
match &s.message_oneof {
StakingVariant::bond(b) => Self::encode_bond(ctx, b),
StakingVariant::bond_extra(b) => Self::encode_bond_extra(b),
StakingVariant::chill(b) => Self::encode_chill(b),
StakingVariant::unbond(b) => Self::encode_unbond(b),
StakingVariant::withdraw_unbonded(b) => Self::encode_withdraw_unbonded(b),
StakingVariant::rebond(b) => Self::encode_rebond(b),
StakingVariant::nominate(b) => Self::encode_nominate(ctx, b),
_ => EncodeError::NotSupported.tw_result(
"Unsupported batched staking variants here (maybe nested batch calls?)".to_string(),
),
}
}
}

impl_enum_scale!(
#[derive(Clone, Debug)]
pub enum GenericUtility {
BatchAll { calls: Vec<RawOwned> } = 0x02,
}
);
Loading