From 0f3860125282fda123ecfff1f48b0d0043d9a6c5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Aug 2020 03:51:02 -0400 Subject: [PATCH] Remove old Substrate pallet (#292) --- bridges/modules/substrate/Cargo.toml | 52 +-- bridges/modules/substrate/src/lib.rs | 469 +-------------------------- 2 files changed, 2 insertions(+), 519 deletions(-) diff --git a/bridges/modules/substrate/Cargo.toml b/bridges/modules/substrate/Cargo.toml index cec9e837eb..0abae27618 100644 --- a/bridges/modules/substrate/Cargo.toml +++ b/bridges/modules/substrate/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-bridge" +name = "pallet-substrate-bridge" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -8,41 +8,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } serde = { version = "1.0", optional = true } hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies -[dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-session] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-finality-grandpa] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - [dependencies.sp-runtime] version = "2.0.0-rc5" tag = 'v2.0.0-rc5' @@ -55,29 +24,10 @@ tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" -# Dev Dependencies -[dev-dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dev-dependencies.sp-state-machine] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' -git = "https://github.com/paritytech/substrate/" - [features] default = ["std"] std = [ "serde", - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-session/std", - "sp-core/std", - "sp-finality-grandpa/std", "sp-runtime/std", "sp-trie/std", - "sp-io/std", ] diff --git a/bridges/modules/substrate/src/lib.rs b/bridges/modules/substrate/src/lib.rs index 3403d91a5b..84fde5c57d 100644 --- a/bridges/modules/substrate/src/lib.rs +++ b/bridges/modules/substrate/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Parity Bridges Common. // Parity Bridges Common is free software: you can redistribute it and/or modify @@ -13,470 +13,3 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . - -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common 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. - -// Parity Bridges Common 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 Parity Bridges Common. If not, see . - -//! # Bridge Module -//! -//! This will eventually have some useful documentation. -//! For now though, enjoy this cow's wisdom. -//! -//!```ignore -//!________________________________________ -//! / You are only young once, but you can \ -//! \ stay immature indefinitely. / -//! ---------------------------------------- -//! \ ^__^ -//! \ (oo)\_______ -//! (__)\ )\/\ -//! ||----w | -//! || || -//!``` - -// TODO: when (if) this module will be resurrected, remove this -#![allow(dead_code)] -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -mod storage_proof; - -use crate::storage_proof::{StorageProof, StorageProofChecker}; -use codec::{Decode, Encode}; -use frame_support::{ - decl_error, decl_module, decl_storage, - dispatch::{DispatchError, DispatchResult}, -}; -use frame_system::{self as system, ensure_signed}; -use sp_finality_grandpa::{AuthorityId, AuthorityWeight, GRANDPA_AUTHORITIES_KEY}; -use sp_runtime::traits::Header; -use storage_proof::Error as StorageError; - -#[derive(Encode, Decode, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct BridgeInfo { - last_finalized_block_number: T::BlockNumber, - last_finalized_block_hash: T::Hash, - last_finalized_state_root: T::Hash, - current_validator_set: Vec<(AuthorityId, AuthorityWeight)>, -} - -impl BridgeInfo { - pub fn new( - block_number: &T::BlockNumber, - block_hash: &T::Hash, - state_root: &T::Hash, - validator_set: Vec<(AuthorityId, AuthorityWeight)>, - ) -> Self { - // I don't like how this is done, should come back to... - BridgeInfo { - last_finalized_block_number: *block_number, - last_finalized_block_hash: *block_hash, - last_finalized_state_root: *state_root, - current_validator_set: validator_set, - } - } -} - -type BridgeId = u64; - -pub trait Trait: system::Trait {} - -decl_storage! { - trait Store for Module as Bridge { - /// The number of current bridges managed by the module. - pub NumBridges get(fn num_bridges) config(): BridgeId; - - /// Maps a bridge id to a bridge struct. Allows a single - /// `bridge` module to manage multiple bridges. - pub TrackedBridges get(fn tracked_bridges): map hasher(blake2_128_concat) BridgeId => Option>; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - #[weight = 0] // TODO: update me - fn initialize_bridge( - origin, - block_header: T::Header, - validator_set: Vec<(AuthorityId, AuthorityWeight)>, - validator_set_proof: StorageProof, - ) { - // NOTE: Will want to make this a governance issued call - let _sender = ensure_signed(origin)?; - - let block_number = block_header.number(); - let block_hash = block_header.hash(); - let state_root = block_header.state_root(); - - Self::check_validator_set_proof(state_root, validator_set_proof, &validator_set)?; - - let bridge_info = BridgeInfo::new(block_number, &block_hash, state_root, validator_set); - - let new_bridge_id = NumBridges::get() + 1; - >::insert(new_bridge_id, bridge_info); - - NumBridges::put(new_bridge_id); - } - - #[weight = 0] // TODO: update me - fn submit_finalized_headers(origin) { - let _sender = ensure_signed(origin)?; - } - } -} - -decl_error! { - // Error for the Bridge module - pub enum Error for Module { - InvalidStorageProof, - StorageRootMismatch, - StorageValueUnavailable, - InvalidValidatorSetProof, - ValidatorSetMismatch, - InvalidAncestryProof, - } -} - -impl Module { - fn check_validator_set_proof( - state_root: &T::Hash, - proof: StorageProof, - validator_set: &[(AuthorityId, AuthorityWeight)], - ) -> DispatchResult { - let checker = >::new(*state_root, proof); - - let checker = checker.map_err(Self::map_storage_err)?; - - // By encoding the given set we should have an easy way to compare - // with the stuff we get out of storage via `read_value` - let encoded_validator_set = validator_set.encode(); - - let c = checker - .read_value(GRANDPA_AUTHORITIES_KEY) - .map_err(Self::map_storage_err)?; - let actual_validator_set = c.ok_or(Error::::StorageValueUnavailable)?; - - if encoded_validator_set == actual_validator_set { - Ok(()) - } else { - Err(Error::::ValidatorSetMismatch.into()) - } - } - - // A naive way to check whether a `child` header is a decendent - // of an `ancestor` header. For this it requires a proof which - // is a chain of headers between (but not including) the `child` - // and `ancestor`. This could be updated to use something like - // Log2 Ancestors (#2053) in the future. - fn verify_ancestry(proof: Vec, ancestor_hash: H::Hash, child: H) -> DispatchResult - where - H: Header, - { - let mut parent_hash = child.parent_hash(); - - // If we find that the header's parent hash matches our ancestor's hash we're done - for header in proof.iter() { - // Need to check that blocks are actually related - if header.hash() != *parent_hash { - break; - } - - parent_hash = header.parent_hash(); - if *parent_hash == ancestor_hash { - return Ok(()); - } - } - - Err(Error::::InvalidAncestryProof.into()) - } - - fn map_storage_err(e: StorageError) -> DispatchError { - match e { - StorageError::StorageRootMismatch => Error::::StorageRootMismatch, - StorageError::StorageValueUnavailable => Error::::StorageValueUnavailable, - } - .into() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use frame_support::{assert_err, assert_ok, impl_outer_origin, parameter_types}; - use sp_core::{Blake2Hasher, Public, H256}; - use sp_runtime::{ - generic::Digest, - testing::Header, - traits::{Header as HeaderT, IdentityLookup}, - Perbill, - }; - - impl_outer_origin! { - pub enum Origin for Test where system = frame_system {} - } - - #[derive(Clone, PartialEq, Eq, Debug)] - pub struct Test; - - type _System = system::Module; - type MockBridge = Module; - - // TODO: Figure out what I actually need from here - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const MinimumPeriod: u64 = 5; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - type DummyAuthorityId = u64; - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = sp_runtime::traits::BlakeTwo256; - type AccountId = DummyAuthorityId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = (); - type MaximumBlockWeight = (); - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = (); - type MaximumBlockLength = (); - type Version = (); - type ModuleToIndex = (); - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = (); - type SystemWeightInfo = (); - } - - impl Trait for Test {} - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { num_bridges: 0 }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - assert_eq!(MockBridge::num_bridges(), 0); - }); - } - - fn get_dummy_authorities() -> Vec<(AuthorityId, AuthorityWeight)> { - let authority1 = (AuthorityId::from_slice(&[1; 32]), 1); - let authority2 = (AuthorityId::from_slice(&[2; 32]), 1); - let authority3 = (AuthorityId::from_slice(&[3; 32]), 1); - - vec![authority1, authority2, authority3] - } - - fn create_dummy_validator_proof(validator_set: Vec<(AuthorityId, AuthorityWeight)>) -> (H256, StorageProof) { - use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; - - let encoded_set = validator_set.encode(); - - // construct storage proof - let backend = >::from(vec![( - None, - vec![(GRANDPA_AUTHORITIES_KEY.to_vec(), Some(encoded_set))], - )]); - let root = backend.storage_root(std::iter::empty()).0; - - // Generates a storage read proof - let proof: StorageProof = prove_read(backend, &[&GRANDPA_AUTHORITIES_KEY[..]]) - .unwrap() - .iter_nodes() - .collect(); - - (root, proof) - } - - #[test] - fn it_can_validate_validator_sets() { - let authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - assert_ok!(MockBridge::check_validator_set_proof(&root, proof, &authorities)); - } - - #[test] - fn it_rejects_invalid_validator_sets() { - let mut authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - // Do something to make the authority set invalid - authorities.reverse(); - let invalid_authorities = authorities; - - assert_err!( - MockBridge::check_validator_set_proof(&root, proof, &invalid_authorities), - Error::::ValidatorSetMismatch - ); - } - - #[test] - fn it_creates_a_new_bridge() { - let authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - let test_header = Header { - parent_hash: H256::default(), - number: 42, - state_root: root, - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - let test_hash = test_header.hash(); - - new_test_ext().execute_with(|| { - assert_eq!(MockBridge::num_bridges(), 0); - dbg!(&test_header); - assert_ok!(MockBridge::initialize_bridge( - Origin::signed(1), - test_header, - authorities.clone(), - proof, - )); - - assert_eq!( - MockBridge::tracked_bridges(1), - Some(BridgeInfo { - last_finalized_block_number: 42, - last_finalized_block_hash: test_hash, - last_finalized_state_root: root, - current_validator_set: authorities.clone(), - }) - ); - - assert_eq!(MockBridge::num_bridges(), 1); - }); - } - - fn build_header_chain(root_header: Header, len: usize) -> Vec
{ - let mut header_chain = vec![root_header]; - for i in 1..len { - let parent = &header_chain[i - 1]; - - let h = Header { - parent_hash: parent.hash(), - number: parent.number() + 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - header_chain.push(h); - } - - // We want our proofs to go from newest to older headers - header_chain.reverse(); - // We don't actually need the oldest header in the proof - header_chain.pop(); - header_chain - } - - #[test] - fn check_that_child_is_ancestor_of_grandparent() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut proof = build_header_chain(ancestor.clone(), 10); - let child = proof.remove(0); - - assert_ok!(MockBridge::verify_ancestry(proof, ancestor.hash(), child)); - } - - #[test] - fn fake_ancestor_is_not_found_in_child_ancestry() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut proof = build_header_chain(ancestor, 10); - let child = proof.remove(0); - - let fake_ancestor = Header { - parent_hash: H256::from_slice(&[1u8; 32]), - number: 42, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - assert_err!( - MockBridge::verify_ancestry(proof, fake_ancestor.hash(), child), - Error::::InvalidAncestryProof - ); - } - - #[test] - fn checker_fails_if_given_an_unrelated_header() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut invalid_proof = build_header_chain(ancestor.clone(), 10); - let child = invalid_proof.remove(0); - - let fake_ancestor = Header { - parent_hash: H256::from_slice(&[1u8; 32]), - number: 42, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - invalid_proof.insert(5, fake_ancestor); - - assert_err!( - MockBridge::verify_ancestry(invalid_proof, ancestor.hash(), child), - Error::::InvalidAncestryProof - ); - } -}