Add SECP256k1/ECDSA support for transaction signing (#3861)

* Add SECP256k1/ECDSA support for transaction signing.

* Refactoring and fixes

* Fix for contracts

* Avoid breaking runtime host function

* Build fixes, make subkey work more generaically.

* Fix tests

* Dedpulicate a bit of code, remove unneeded code, docs

* Bump runtime version

* Fix a test and clean up some code.

* Derivation can derive seed.

* Whitespace

* Bump runtime again.

* Update core/primitives/src/crypto.rs

Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update core/primitives/src/ecdsa.rs

Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Fix AppVerify
This commit is contained in:
Gavin Wood
2019-10-24 10:59:09 +02:00
committed by GitHub
parent 62a238a81b
commit d97775542a
30 changed files with 1286 additions and 419 deletions
+6 -65
View File
@@ -21,71 +21,24 @@ use sr_primitives::app_crypto::RuntimeAppPublic;
use sr_primitives::traits::Extrinsic as ExtrinsicT;
/// A trait responsible for signing a payload using given account.
pub trait Signer<Account, Signature> {
pub trait Signer<Public, Signature> {
/// Sign any encodable payload with given account and produce a signature.
///
/// Returns `Some` if signing succeeded and `None` in case the `account` couldn't be used.
fn sign<Payload: Encode>(account: Account, payload: &Payload) -> Option<Signature>;
fn sign<Payload: Encode>(public: Public, payload: &Payload) -> Option<Signature>;
}
impl<Account, Signature, AppPublic> Signer<Account, Signature> for AppPublic where
AppPublic: RuntimeAppPublic + From<Account>,
impl<Public, Signature, AppPublic> Signer<Public, Signature> for AppPublic where
AppPublic: RuntimeAppPublic + From<Public>,
AppPublic::Signature: Into<Signature>,
{
fn sign<Payload: Encode>(account: Account, raw_payload: &Payload) -> Option<Signature> {
fn sign<Payload: Encode>(public: Public, raw_payload: &Payload) -> Option<Signature> {
raw_payload.using_encoded(|payload| {
AppPublic::from(account).sign(&payload).map(Into::into)
AppPublic::from(public).sign(&payload).map(Into::into)
})
}
}
/// Creates runtime-specific signed transaction.
pub trait CreateTransaction<T: crate::Trait, Extrinsic: ExtrinsicT> {
type Signature;
/// Attempt to create signed extrinsic data that encodes call from given account.
///
/// Runtime implementation is free to construct the payload to sign and the signature
/// in any way it wants.
/// Returns `None` if signed extrinsic could not be created (either because signing failed
/// or because of any other runtime-specific reason).
fn create_transaction<F: Signer<T::AccountId, Self::Signature>>(
call: Extrinsic::Call,
account: T::AccountId,
nonce: T::Index,
) -> Option<(Extrinsic::Call, Extrinsic::SignaturePayload)>;
}
/// A trait to sign and submit transactions in offchain calls.
pub trait SubmitSignedTransaction<T: crate::Trait, Call> {
/// Unchecked extrinsic type.
type Extrinsic: ExtrinsicT<Call=Call> + codec::Encode;
/// A runtime-specific type to produce signed data for the extrinsic.
type CreateTransaction: CreateTransaction<T, Self::Extrinsic>;
/// A type used to sign transactions created using `CreateTransaction`.
type Signer: Signer<
T::AccountId,
<Self::CreateTransaction as CreateTransaction<T, Self::Extrinsic>>::Signature,
>;
/// Sign given call and submit it to the transaction pool.
///
/// Returns `Ok` if the transaction was submitted correctly
/// and `Err` if the key for given `id` was not found or the
/// transaction was rejected from the pool.
fn sign_and_submit(call: impl Into<Call>, id: T::AccountId) -> Result<(), ()> {
let call = call.into();
let expected = <crate::Module<T>>::account_nonce(&id);
let (call, signature_data) = Self::CreateTransaction
::create_transaction::<Self::Signer>(call, id, expected)
.ok_or(())?;
let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?;
runtime_io::submit_transaction(xt.encode())
}
}
/// A trait to submit unsigned transactions in offchain calls.
pub trait SubmitUnsignedTransaction<T: crate::Trait, Call> {
/// Unchecked extrinsic type.
@@ -114,18 +67,6 @@ impl<S, C, E> Default for TransactionSubmitter<S, C, E> {
}
}
/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime.
impl<T, E, S, C, Call> SubmitSignedTransaction<T, Call> for TransactionSubmitter<S, C, E> where
T: crate::Trait,
C: CreateTransaction<T, E>,
S: Signer<T::AccountId, <C as CreateTransaction<T, E>>::Signature>,
E: ExtrinsicT<Call=Call> + codec::Encode,
{
type Extrinsic = E;
type CreateTransaction = C;
type Signer = S;
}
/// A blanket impl to use the same submitter for usigned transactions as well.
impl<T, E, S, C, Call> SubmitUnsignedTransaction<T, Call> for TransactionSubmitter<S, C, E> where
T: crate::Trait,