diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs
index 953d200113039..f448938d8e483 100644
--- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs
+++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs
@@ -20,6 +20,7 @@
use std::fmt;
use rstd::prelude::*;
+use runtime_io::blake2_256;
use codec::{Decode, Encode, Input, Compact};
use traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup,
Checkable, Extrinsic};
@@ -85,14 +86,20 @@ where
Some((signed, signature, index, era)) => {
let h = context.block_number_to_hash(BlockNumber::sa(era.birth(context.current_height().as_())))
.ok_or("transaction birth block ancient")?;
- let payload = (index, self.function, era, h);
let signed = context.lookup(signed)?;
- if !::verify_encoded_lazy(&signature, &payload, &signed) {
+ let raw_payload = (index, self.function, era, h);
+ if !raw_payload.using_encoded(|payload| {
+ if payload.len() > 256 {
+ signature.verify(&blake2_256(payload)[..], &signed)
+ } else {
+ signature.verify(payload, &signed)
+ }
+ }) {
return Err("bad signature in extrinsic")
}
CheckedExtrinsic {
- signed: Some((signed, (payload.0).0)),
- function: payload.1,
+ signed: Some((signed, (raw_payload.0).0)),
+ function: raw_payload.1,
}
}
None => CheckedExtrinsic {
@@ -182,6 +189,7 @@ impl
fmt::Debug for UncheckedMortalCompactExtri
#[cfg(test)]
mod tests {
use super::*;
+ use runtime_io::blake2_256;
struct TestContext;
impl Lookup for TestContext {
@@ -208,78 +216,84 @@ mod tests {
}
}
- const DUMMY_FUNCTION: u64 = 0;
const DUMMY_ACCOUNTID: u64 = 0;
- type Ex = UncheckedMortalCompactExtrinsic;
- type CEx = CheckedExtrinsic;
+ type Ex = UncheckedMortalCompactExtrinsic, TestSig>;
+ type CEx = CheckedExtrinsic>;
#[test]
fn unsigned_codec_should_work() {
- let ux = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ux = Ex::new_unsigned(vec![0u8;0]);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
}
#[test]
fn signed_codec_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal());
+ let encoded = ux.encode();
+ assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
+ }
+
+ #[test]
+ fn large_signed_codec_should_work() {
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8; 257], Era::immortal(), 0u64).using_encoded(blake2_256)[..].to_owned()), Era::immortal());
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
}
#[test]
fn unsigned_check_should_work() {
- let ux = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ux = Ex::new_unsigned(vec![0u8;0]);
assert!(!ux.is_signed().unwrap_or(false));
assert!(>::check(ux, &TestContext).is_ok());
}
#[test]
fn badly_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal());
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn immortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal());
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn mortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), DUMMY_FUNCTION, Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42));
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn later_mortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), DUMMY_FUNCTION, Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11));
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn too_late_mortal_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn too_early_mortal_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn encoding_matches_vec() {
- let ex = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ex = Ex::new_unsigned(vec![0u8;0]);
let encoded = ex.encode();
let decoded = Ex::decode(&mut encoded.as_slice()).unwrap();
assert_eq!(decoded, ex);
diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs
index 8aa6faa467411..8630706795bb1 100644
--- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs
+++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs
@@ -20,6 +20,7 @@
use std::fmt;
use rstd::prelude::*;
+use runtime_io::blake2_256;
use codec::{Decode, Encode, Input};
use traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup,
Checkable, Extrinsic};
@@ -84,14 +85,21 @@ where
Some((signed, signature, index, era)) => {
let h = context.block_number_to_hash(BlockNumber::sa(era.birth(context.current_height().as_())))
.ok_or("transaction birth block ancient")?;
- let payload = (index, self.function, era, h);
let signed = context.lookup(signed)?;
- if !::verify_encoded_lazy(&signature, &payload, &signed) {
+ let raw_payload = (index, self.function, era, h);
+
+ if !raw_payload.using_encoded(|payload| {
+ if payload.len() > 256 {
+ signature.verify(&blake2_256(payload)[..], &signed)
+ } else {
+ signature.verify(payload, &signed)
+ }
+ }) {
return Err("bad signature in extrinsic")
}
CheckedExtrinsic {
- signed: Some((signed, payload.0)),
- function: payload.1,
+ signed: Some((signed, raw_payload.0)),
+ function: raw_payload.1,
}
}
None => CheckedExtrinsic {
@@ -180,6 +188,7 @@ impl fmt::Debug for UncheckedMortalExtrinsic;
- type CEx = CheckedExtrinsic;
+ type Ex = UncheckedMortalExtrinsic, TestSig>;
+ type CEx = CheckedExtrinsic>;
#[test]
fn unsigned_codec_should_work() {
- let ux = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ux = Ex::new_unsigned(vec![0u8;0]);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
}
#[test]
fn signed_codec_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal());
+ let encoded = ux.encode();
+ assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
+ }
+
+ #[test]
+ fn large_signed_codec_should_work() {
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8; 257], Era::immortal(), 0u64).using_encoded(blake2_256)[..].to_owned()), Era::immortal());
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
}
#[test]
fn unsigned_check_should_work() {
- let ux = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ux = Ex::new_unsigned(vec![0u8;0]);
assert!(!ux.is_signed().unwrap_or(false));
assert!(>::check(ux, &TestContext).is_ok());
}
#[test]
fn badly_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal());
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn immortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal());
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal());
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn mortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42));
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn later_mortal_signed_check_should_work() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11));
assert!(ux.is_signed().unwrap_or(false));
- assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION }));
+ assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] }));
}
#[test]
fn too_late_mortal_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn too_early_mortal_signed_check_should_fail() {
- let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43));
+ let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43));
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
#[test]
fn encoding_matches_vec() {
- let ex = Ex::new_unsigned(DUMMY_FUNCTION);
+ let ex = Ex::new_unsigned(vec![0u8;0]);
let encoded = ex.encode();
let decoded = Ex::decode(&mut encoded.as_slice()).unwrap();
assert_eq!(decoded, ex);
diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm
index cf137047c9329..00c4d4ce9f0f7 100644
Binary files a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ
diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs
index 24ba252019a25..f769b284e2065 100644
--- a/node/executor/src/lib.rs
+++ b/node/executor/src/lib.rs
@@ -72,7 +72,11 @@ mod tests {
let era = Era::mortal(256, 0);
let payload = (index.into(), xt.function, era, GENESIS_HASH);
let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap());
- let signature = pair.sign(&payload.encode()).into();
+ let signature = payload.using_encoded(|b| if b.len() > 256 {
+ pair.sign(&runtime_io::blake2_256(b))
+ } else {
+ pair.sign(b)
+ }).into();
UncheckedExtrinsic {
signature: Some((indices::address::Address::Id(signed), signature, payload.0, era)),
function: payload.1,
diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs
index 183ce7a26e61d..625e00921dedd 100644
--- a/node/runtime/src/lib.rs
+++ b/node/runtime/src/lib.rs
@@ -66,8 +66,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
- spec_version: 17,
- impl_version: 17,
+ spec_version: 18,
+ impl_version: 18,
apis: RUNTIME_API_VERSIONS,
};
diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm
index 1f37f30dd8b6f..01f64762a5e60 100644
Binary files a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ