Skip to content

Commit

Permalink
support eip-712 and eth signature
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Sep 22, 2021
1 parent 8dbdde4 commit b69a220
Show file tree
Hide file tree
Showing 11 changed files with 525 additions and 24 deletions.
6 changes: 5 additions & 1 deletion Cargo.lock

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

19 changes: 18 additions & 1 deletion modules/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub use module_support::{
pub use orml_traits::currency::TransferAll;
use primitive_types::{H160, H256, U256};
pub use primitives::{
evm::{Account, CallInfo, CreateInfo, EvmAddress, ExecutionInfo, Log, Vicinity},
evm::{Account, CallInfo, CreateInfo, EvmAddress, ExecutionInfo, Log, TransactionAction, Vicinity},
ReserveIdentifier, H160_PREFIX_DEXSHARE, H160_PREFIX_TOKEN, MIRRORED_NFT_ADDRESS_START, PRECOMPILE_ADDRESS_START,
SYSTEM_CONTRACT_ADDRESS_PREFIX,
};
Expand Down Expand Up @@ -480,6 +480,23 @@ pub mod module {

#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(T::GasToWeight::convert(*gas_limit))]
#[transactional]
pub fn eth_call(
origin: OriginFor<T>,
action: TransactionAction,
input: Vec<u8>,
value: BalanceOf<T>,
gas_limit: u64,
storage_limit: u32,
_valid_until: T::BlockNumber, // checked by tx validation logic
) -> DispatchResultWithPostInfo {
match action {
TransactionAction::Call(target) => Self::call(origin, target, input, value, gas_limit, storage_limit),
TransactionAction::Create => Self::create(origin, input, value, gas_limit, storage_limit),
}
}

/// Issue an EVM call operation. This is similar to a message call
/// transaction in Ethereum.
///
Expand Down
6 changes: 5 additions & 1 deletion modules/transaction-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ where
/// Require the transactor pay for themselves and maybe include a tip to
/// gain additional priority in the queue.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct ChargeTransactionPayment<T: Config + Send + Sync>(#[codec(compact)] PalletBalanceOf<T>);
pub struct ChargeTransactionPayment<T: Config + Send + Sync>(#[codec(compact)] pub PalletBalanceOf<T>);

impl<T: Config + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T> {
#[cfg(feature = "std")]
Expand Down Expand Up @@ -697,6 +697,10 @@ where
WithdrawReasons::TRANSACTION_PAYMENT | WithdrawReasons::TIP
};

sp_std::if_std! {
println!("{:?}", who);
};

Pallet::<T>::ensure_can_charge_fee(who, fee, reason);

// withdraw native currency as fee
Expand Down
24 changes: 21 additions & 3 deletions primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,50 @@ bstringify = "0.1.2"
serde = { version = "1.0.124", optional = true }
codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["max-encoded-len"] }
num_enum = { version = "0.5.1", default-features = false }
parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] }

sp-core = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }
sp-runtime = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }
sp-std = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }
sp-io = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }
sp-api = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }

frame-support = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9", default-features = false }

evm = { version = "0.30.0", default-features = false, features = ["with-codec"] }
ethereum = { version = "0.9.0", default-features = false, features = ["with-codec"] }

chainbridge = { git = "https:/AcalaNetwork/chainbridge-substrate", default-features = false }
nutsfinance-stable-asset = { version = "0.1.0", default-features = false, path = "../ecosystem-modules/stable-asset/lib/stable-asset", package = "nutsfinance-stable-asset" }

[dev-dependencies]
sha3 = { version = "0.9.1" }
serde_json = { version = "1.0.64" }
hex-literal = "0.3.1"
primitives-proc-macro = { path = "./proc-macro" }
frame-support = { git = "https:/paritytech/substrate", branch = "polkadot-v0.9.9" }

[features]
default = ["std"]
std = [
"serde",
"codec/std",
"num_enum/std",
"parity-util-mem/std",

"sp-runtime/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"sp-api/std",

"frame-support/std",

"evm/std",
"evm/with-serde",
"ethereum/std",
"ethereum/with-serde",

"chainbridge/std",
"nutsfinance-stable-asset/std"
"nutsfinance-stable-asset/std",
]
runtime-benchmarks = [
"chainbridge/runtime-benchmarks",
Expand Down
18 changes: 16 additions & 2 deletions primitives/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::Balance;
use crate::{Balance, Nonce};
use codec::{Decode, Encode};
use evm::ExitReason;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use sp_core::{H160, U256};
use sp_core::{H160, H256, U256};
use sp_runtime::RuntimeDebug;
use sp_std::vec::Vec;

pub use ethereum::TransactionAction;
pub use evm::backend::{Basic as Account, Log};
pub use evm::Config;

Expand Down Expand Up @@ -79,3 +80,16 @@ pub struct EstimateResourcesRequest {
/// Data
pub data: Option<Vec<u8>>,
}

pub struct EthereumTransactionMessage {
pub nonce: Nonce,
pub tip: Balance,
pub gas_limit: u64,
pub storage_limit: u32,
pub action: TransactionAction,
pub value: Balance,
pub input: Vec<u8>,
pub chain_id: u64,
pub genesis: H256,
pub valid_until: u32,
}
9 changes: 7 additions & 2 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

pub mod currency;
pub mod evm;
pub mod signature;
pub mod unchecked_extrinsic;

use codec::{Decode, Encode, MaxEncodedLen};
use core::ops::Range;
use sp_runtime::{
generic,
traits::{BlakeTwo256, IdentifyAccount, Verify},
MultiSignature, RuntimeDebug,
RuntimeDebug,
};
use sp_std::{convert::Into, prelude::*};

Expand All @@ -45,7 +47,7 @@ pub type BlockNumber = u32;

/// Alias to 512-bit hash when used in the context of a transaction signature on
/// the chain.
pub type Signature = MultiSignature;
pub type Signature = signature::AcalaMultiSignature;

/// Alias to the public key used for this chain, actually a `MultiSigner`. Like
/// the signature, this also isn't a fixed size when encoded, as different
Expand All @@ -60,6 +62,9 @@ pub type AccountId = <AccountPublic as IdentifyAccount>::AccountId;
/// them.
pub type AccountIndex = u32;

/// The address format for describing accounts.
pub type Address = sp_runtime::MultiAddress<AccountId, AccountIndex>;

/// Index of a transaction in the chain. 32-bit should be plenty.
pub type Nonce = u32;

Expand Down
116 changes: 116 additions & 0 deletions primitives/src/signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// This file is part of Acala.

// Copyright (C) 2020-2021 Acala Foundation.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use codec::{Decode, Encode};
use sp_runtime::{
traits::{Lazy, Verify},
AccountId32, MultiSigner, RuntimeDebug,
};

use sp_core::{crypto::Public, ecdsa, ed25519, sr25519};

use sp_std::{convert::TryFrom, prelude::*};

#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)]
pub enum AcalaMultiSignature {
/// An Ed25519 signature.
Ed25519(ed25519::Signature),
/// An Sr25519 signature.
Sr25519(sr25519::Signature),
/// An ECDSA/SECP256k1 signature.
Ecdsa(ecdsa::Signature),
// An Ethereum compatible SECP256k1 signature.
Ethereum([u8; 65]),
// An Ethereum SECP256k1 signature using Eip712 for message encoding.
AcalaEip712([u8; 65]),
}

impl From<ed25519::Signature> for AcalaMultiSignature {
fn from(x: ed25519::Signature) -> Self {
Self::Ed25519(x)
}
}

impl TryFrom<AcalaMultiSignature> for ed25519::Signature {
type Error = ();
fn try_from(m: AcalaMultiSignature) -> Result<Self, Self::Error> {
if let AcalaMultiSignature::Ed25519(x) = m {
Ok(x)
} else {
Err(())
}
}
}

impl From<sr25519::Signature> for AcalaMultiSignature {
fn from(x: sr25519::Signature) -> Self {
Self::Sr25519(x)
}
}

impl TryFrom<AcalaMultiSignature> for sr25519::Signature {
type Error = ();
fn try_from(m: AcalaMultiSignature) -> Result<Self, Self::Error> {
if let AcalaMultiSignature::Sr25519(x) = m {
Ok(x)
} else {
Err(())
}
}
}

impl From<ecdsa::Signature> for AcalaMultiSignature {
fn from(x: ecdsa::Signature) -> Self {
Self::Ecdsa(x)
}
}

impl TryFrom<AcalaMultiSignature> for ecdsa::Signature {
type Error = ();
fn try_from(m: AcalaMultiSignature) -> Result<Self, Self::Error> {
if let AcalaMultiSignature::Ecdsa(x) = m {
Ok(x)
} else {
Err(())
}
}
}

impl Default for AcalaMultiSignature {
fn default() -> Self {
Self::Ed25519(Default::default())
}
}

impl Verify for AcalaMultiSignature {
type Signer = MultiSigner;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
match (self, signer) {
(Self::Ed25519(ref sig), who) => sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())),
(Self::Sr25519(ref sig), who) => sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())),
(Self::Ecdsa(ref sig), who) => {
let m = sp_io::hashing::blake2_256(msg.get());
match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) {
Ok(pubkey) => &sp_io::hashing::blake2_256(pubkey.as_ref()) == <dyn AsRef<[u8; 32]>>::as_ref(who),
_ => false,
}
}
_ => false, // Arbitrary message verification is not supported
}
}
}
Loading

0 comments on commit b69a220

Please sign in to comment.