diff --git a/substrate/srml/consensus/src/lib.rs b/substrate/srml/consensus/src/lib.rs
index 72ef1e7f5be809ae33bb20b06b4c8350eff04c9d..241f78ce199b40d6c1098d6d975ab654b4e99b2d 100644
--- a/substrate/srml/consensus/src/lib.rs
+++ b/substrate/srml/consensus/src/lib.rs
@@ -51,6 +51,9 @@ use primitives::bft::MisbehaviorReport;
 use substrate_primitives::storage::well_known_keys;
 use system::{ensure_signed, ensure_inherent};
 
+mod mock;
+mod tests;
+
 struct AuthorityStorageVec<S: codec::Codec + Default>(rstd::marker::PhantomData<S>);
 impl<S: codec::Codec + Default> StorageVec for AuthorityStorageVec<S> {
 	type Item = S;
@@ -90,13 +93,13 @@ impl<SessionKey: Member> RawLog<SessionKey> {
 
 // Implementation for tests outside of this crate.
 #[cfg(any(feature = "std", test))]
-impl<N> From<RawLog<N>> for primitives::testing::DigestItem {
+impl<N> From<RawLog<N>> for primitives::testing::DigestItem where N: Into<u64> {
 	fn from(log: RawLog<N>) -> primitives::testing::DigestItem {
 		match log {
 			RawLog::AuthoritiesChange(authorities) =>
 				primitives::generic::DigestItem::AuthoritiesChange
 					::<substrate_primitives::H256, u64>(authorities.into_iter()
-						.enumerate().map(|(i, _)| i as u64).collect()),
+						.map(Into::into).collect()),
 		}
 	}
 }
@@ -211,13 +214,21 @@ impl<T: Trait> Module<T> {
 		<OriginalAuthorities<T>>::put(current_authorities.unwrap_or_else(||
 			AuthorityStorageVec::<T::SessionKey>::items()));
 	}
+
+	/// Deposit one of this module's logs.
+	fn deposit_log(log: Log<T>) {
+		<system::Module<T>>::deposit_log(<T as Trait>::Log::from(log).into());
+	}
 }
 
 /// Finalization hook for the consensus module.
 impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
 	fn on_finalise(_n: T::BlockNumber) {
-		if let Some(_) = <OriginalAuthorities<T>>::take() {
-			// TODO: call Self::deposit_log
+		if let Some(original_authorities) = <OriginalAuthorities<T>>::take() {
+			let current_authorities = AuthorityStorageVec::<T::SessionKey>::items();
+			if current_authorities != original_authorities {
+				Self::deposit_log(RawLog::AuthoritiesChange(current_authorities));
+			}
 		}
 	}
 }
diff --git a/substrate/srml/consensus/src/mock.rs b/substrate/srml/consensus/src/mock.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e86731f52dbb7f6a47da03929b2c5cbb8eeba1b4
--- /dev/null
+++ b/substrate/srml/consensus/src/mock.rs
@@ -0,0 +1,62 @@
+// Copyright 2018 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate 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.
+
+// Substrate 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 Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Test utilities
+
+#![cfg(test)]
+
+use primitives::{BuildStorage, testing::{Digest, DigestItem, Header}};
+use runtime_io;
+use substrate_primitives::{H256, Blake2Hasher, RlpCodec};
+use {GenesisConfig, Trait, Module, system};
+
+impl_outer_origin!{
+	pub enum Origin for Test {}
+}
+
+// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
+#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
+pub struct Test;
+impl Trait for Test {
+	const NOTE_OFFLINE_POSITION: u32 = 1;
+	type Log = DigestItem;
+	type SessionKey = u64;
+	type OnOfflineValidator = ();
+}
+impl system::Trait for Test {
+	type Origin = Origin;
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type Hashing = ::primitives::traits::BlakeTwo256;
+	type Digest = Digest;
+	type AccountId = u64;
+	type Header = Header;
+	type Event = ();
+	type Log = DigestItem;
+}
+
+pub fn new_test_ext(authorities: Vec<u64>) -> runtime_io::TestExternalities<Blake2Hasher, RlpCodec> {
+	let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap();
+	t.extend(GenesisConfig::<Test>{
+		code: vec![],
+		authorities,
+	}.build_storage().unwrap());
+	t.into()
+}
+
+pub type System = system::Module<Test>;
+pub type Consensus = Module<Test>;
diff --git a/substrate/srml/consensus/src/tests.rs b/substrate/srml/consensus/src/tests.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2e581759b5d983e501fc4c113508ec02d2a592ff
--- /dev/null
+++ b/substrate/srml/consensus/src/tests.rs
@@ -0,0 +1,66 @@
+// Copyright 2017 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate 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.
+
+// Substrate 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 Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Tests for the module.
+
+#![cfg(test)]
+
+use super::*;
+use primitives::{generic, testing};
+use runtime_io::with_externalities;
+use substrate_primitives::H256;
+use mock::{Consensus, System, new_test_ext};
+
+#[test]
+fn authorities_change_logged() {
+	with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
+		System::initialise(&1, &Default::default(), &Default::default());
+		Consensus::set_authorities(&[4, 5, 6]);
+		Consensus::on_finalise(1);
+		let header = System::finalise();
+		assert_eq!(header.digest, testing::Digest {
+			logs: vec![
+				generic::DigestItem::AuthoritiesChange::<H256, u64>(vec![4, 5, 6]),
+			],
+		});
+	});
+}
+
+#[test]
+fn authorities_change_is_not_logged_when_not_changed() {
+	with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
+		System::initialise(&1, &Default::default(), &Default::default());
+		Consensus::on_finalise(1);
+		let header = System::finalise();
+		assert_eq!(header.digest, testing::Digest {
+			logs: vec![],
+		});
+	});
+}
+
+#[test]
+fn authorities_change_is_not_logged_when_changed_back_to_original() {
+	with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
+		System::initialise(&1, &Default::default(), &Default::default());
+		Consensus::set_authorities(&[4, 5, 6]);
+		Consensus::set_authorities(&[1, 2, 3]);
+		Consensus::on_finalise(1);
+		let header = System::finalise();
+		assert_eq!(header.digest, testing::Digest {
+			logs: vec![],
+		});
+	});
+}