diff --git a/Cargo.lock b/Cargo.lock
index ea4d2a453..5edf60356 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -805,7 +805,6 @@ dependencies = [
  "grin_util 0.2.0",
  "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "prettytable-rs 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/servers/tests/framework/mod.rs b/servers/tests/framework/mod.rs
index 8efd8a2da..7fad52ee0 100644
--- a/servers/tests/framework/mod.rs
+++ b/servers/tests/framework/mod.rs
@@ -23,11 +23,11 @@ extern crate grin_wallet as wallet;
 
 extern crate blake2_rfc as blake2;
 
-use std::thread;
-use std::time;
 use std::default::Default;
 use std::fs;
 use std::sync::{Arc, Mutex};
+use std::thread;
+use std::time;
 
 use wallet::WalletConfig;
 
diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml
index ef7635015..8bd8a916a 100644
--- a/wallet/Cargo.toml
+++ b/wallet/Cargo.toml
@@ -14,7 +14,6 @@ failure_derive = "0.1"
 futures = "0.1"
 hyper = "0.11"
 iron = "0.5"
-lazy_static = "0.2"
 prettytable-rs = "0.6"
 rand = "0.3"
 router = "0.5"
diff --git a/wallet/src/checker.rs b/wallet/src/checker.rs
index 1fac0332d..9120f22a8 100644
--- a/wallet/src/checker.rs
+++ b/wallet/src/checker.rs
@@ -226,6 +226,9 @@ fn refresh_output_state(
 }
 
 fn clean_old_unconfirmed(config: &WalletConfig, tip: &api::Tip) -> Result<(), Error> {
+	if tip.height < 500 {
+		return Ok(());
+	}
 	WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
 		wallet_data.outputs.retain(|_, ref mut out| {
 			!(out.status == OutputStatus::Unconfirmed && out.height > 0
diff --git a/wallet/src/grinwallet/keys.rs b/wallet/src/grinwallet/keys.rs
index d20c1cb03..b77c97ce7 100644
--- a/wallet/src/grinwallet/keys.rs
+++ b/wallet/src/grinwallet/keys.rs
@@ -13,17 +13,8 @@
 // limitations under the License.
 
 //! Grin Wallet specific key management functions
-use rand::thread_rng;
-use uuid::Uuid;
-
-use core::core::{amount_to_hr_string, Committed, Transaction};
-use failure::ResultExt;
-use keychain::{BlindSum, BlindingFactor, Identifier, Keychain};
-use libwallet::{aggsig, build};
+use keychain::{Identifier, Keychain};
 use types::*;
-use util::secp::Signature;
-use util::secp::key::{PublicKey, SecretKey};
-use util::{secp, LOGGER};
 
 /// Get our next available key
 pub fn new_output_key(
diff --git a/wallet/src/grinwallet/mod.rs b/wallet/src/grinwallet/mod.rs
index 06c764d13..4371e24dc 100644
--- a/wallet/src/grinwallet/mod.rs
+++ b/wallet/src/grinwallet/mod.rs
@@ -25,5 +25,6 @@
 #![deny(unused_mut)]
 #![warn(missing_docs)]
 
-pub mod selection;
 pub mod keys;
+pub mod selection;
+pub mod sigcontext;
diff --git a/wallet/src/grinwallet/selection.rs b/wallet/src/grinwallet/selection.rs
index 9e2f92935..ba26db944 100644
--- a/wallet/src/grinwallet/selection.rs
+++ b/wallet/src/grinwallet/selection.rs
@@ -15,9 +15,9 @@
 //! Selection of inputs for building transactions
 
 use failure::ResultExt;
-use grinwallet::keys;
+use grinwallet::{keys, sigcontext};
 use keychain::{Identifier, Keychain};
-use libwallet::{aggsig, build, transaction};
+use libwallet::{build, transaction};
 use types::*;
 
 /// Initialise a transaction on the sender side, returns a corresponding
@@ -28,7 +28,6 @@ use types::*;
 pub fn build_send_tx_slate(
 	config: &WalletConfig,
 	keychain: &Keychain,
-	context_manager: &mut aggsig::ContextManager,
 	num_participants: usize,
 	amount: u64,
 	current_height: u64,
@@ -36,7 +35,14 @@ pub fn build_send_tx_slate(
 	lock_height: u64,
 	max_outputs: usize,
 	selection_strategy_is_use_all: bool,
-) -> Result<(transaction::Slate, impl FnOnce() -> Result<(), Error>), Error> {
+) -> Result<
+	(
+		transaction::Slate,
+		sigcontext::Context,
+		impl FnOnce() -> Result<(), Error>,
+	),
+	Error,
+> {
 	let (elems, inputs, change_id, amount, fee) = select_send_tx(
 		config,
 		keychain,
@@ -55,11 +61,12 @@ pub fn build_send_tx_slate(
 	slate.lock_height = lock_height;
 	slate.fee = fee;
 
-	let blinding = slate.add_transaction_elements(keychain, elems)?;
+	let blinding = slate
+		.add_transaction_elements(keychain, elems)
+		.context(ErrorKind::LibWalletError)?;
 	// Create our own private context
-	let mut context = context_manager.create_context(
+	let mut context = sigcontext::Context::new(
 		keychain.secp(),
-		&slate.id,
 		blinding.secret_key(keychain.secp()).unwrap(),
 	);
 
@@ -93,9 +100,7 @@ pub fn build_send_tx_slate(
 			}*/		})
 	};
 
-	context_manager.save_context(context);
-
-	Ok((slate, update_sender_wallet_fn))
+	Ok((slate, context, update_sender_wallet_fn))
 }
 
 /// Creates a new output in the wallet for the recipient,
@@ -105,9 +110,15 @@ pub fn build_send_tx_slate(
 pub fn build_recipient_output_with_slate(
 	config: &WalletConfig,
 	keychain: &Keychain,
-	context_manager: &mut aggsig::ContextManager,
 	slate: &mut transaction::Slate,
-) -> Result<(Identifier, impl FnOnce() -> Result<(), Error>), Error> {
+) -> Result<
+	(
+		Identifier,
+		sigcontext::Context,
+		impl FnOnce() -> Result<(), Error>,
+	),
+	Error,
+> {
 	// Create a potential output for this transaction
 	let (key_id, derivation) = keys::new_output_key(config, keychain)?;
 
@@ -115,14 +126,15 @@ pub fn build_recipient_output_with_slate(
 	let root_key_id = keychain.root_key_id();
 	let key_id_inner = key_id.clone();
 	let amount = slate.amount;
+	let height = slate.height;
 
-	let blinding =
-		slate.add_transaction_elements(keychain, vec![build::output(amount, key_id.clone())])?;
+	let blinding = slate
+		.add_transaction_elements(keychain, vec![build::output(amount, key_id.clone())])
+		.context(ErrorKind::LibWalletError)?;
 
 	// Add blinding sum to our context
-	let mut context = context_manager.create_context(
+	let mut context = sigcontext::Context::new(
 		keychain.secp(),
-		&slate.id,
 		blinding.secret_key(keychain.secp()).unwrap(),
 	);
 
@@ -138,7 +150,7 @@ pub fn build_recipient_output_with_slate(
 				n_child: derivation,
 				value: amount,
 				status: OutputStatus::Unconfirmed,
-				height: 0,
+				height: height,
 				lock_height: 0,
 				is_coinbase: false,
 				block: None,
@@ -146,8 +158,7 @@ pub fn build_recipient_output_with_slate(
 			});
 		})
 	};
-	context_manager.save_context(context);
-	Ok((key_id, wallet_add_fn))
+	Ok((key_id, context, wallet_add_fn))
 }
 
 /// Builds a transaction to send to someone from the HD seed associated with the
@@ -203,7 +214,7 @@ pub fn select_send_tx(
 	// sender
 	let mut fee;
 	// First attempt to spend without change
-	fee = tx_fee(coins.len(), 1, coins_proof_count(&coins), None);
+	fee = transaction::tx_fee(coins.len(), 1, coins_proof_count(&coins), None);
 	let mut total: u64 = coins.iter().map(|c| c.value).sum();
 	let mut amount_with_fee = amount + fee;
 
@@ -213,7 +224,7 @@ pub fn select_send_tx(
 
 	// Check if we need to use a change address
 	if total > amount_with_fee {
-		fee = tx_fee(coins.len(), 2, coins_proof_count(&coins), None);
+		fee = transaction::tx_fee(coins.len(), 2, coins_proof_count(&coins), None);
 		amount_with_fee = amount + fee;
 
 		// Here check if we have enough outputs for the amount including fee otherwise
@@ -235,14 +246,15 @@ pub fn select_send_tx(
 					selection_strategy_is_use_all,
 				))
 			})?;
-			fee = tx_fee(coins.len(), 2, coins_proof_count(&coins), None);
+			fee = transaction::tx_fee(coins.len(), 2, coins_proof_count(&coins), None);
 			total = coins.iter().map(|c| c.value).sum();
 			amount_with_fee = amount + fee;
 		}
 	}
 
 	// build transaction skeleton with inputs and change
-	let (mut parts, change_key) = inputs_and_change(&coins, config, keychain, amount, fee)?;
+	let (mut parts, change_key) =
+		inputs_and_change(&coins, config, keychain, current_height, amount, fee)?;
 
 	// This is more proof of concept than anything but here we set lock_height
 	// on tx being sent (based on current chain height via api).
@@ -261,6 +273,7 @@ pub fn inputs_and_change(
 	coins: &Vec<OutputData>,
 	config: &WalletConfig,
 	keychain: &Keychain,
+	height: u64,
 	amount: u64,
 	fee: u64,
 ) -> Result<(Vec<Box<build::Append>>, Option<Identifier>), Error> {
@@ -310,7 +323,7 @@ pub fn inputs_and_change(
 				n_child: change_derivation,
 				value: change as u64,
 				status: OutputStatus::Unconfirmed,
-				height: 0,
+				height: height,
 				lock_height: 0,
 				is_coinbase: false,
 				block: None,
diff --git a/wallet/src/grinwallet/sigcontext.rs b/wallet/src/grinwallet/sigcontext.rs
new file mode 100644
index 000000000..d49fab7a6
--- /dev/null
+++ b/wallet/src/grinwallet/sigcontext.rs
@@ -0,0 +1,84 @@
+// Copyright 2018 The Grin Developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//! Signature context holder helper (may be removed or replaced eventually)
+use keychain::extkey::Identifier;
+use libwallet::aggsig;
+use util::secp::key::{PublicKey, SecretKey};
+use util::secp::{self, Secp256k1};
+
+#[derive(Clone, Debug)]
+/// Holds the context for a single aggsig transaction
+pub struct Context {
+	/// Secret key (of which public is shared)
+	pub sec_key: SecretKey,
+	/// Secret nonce (of which public is shared)
+	/// (basically a SecretKey)
+	pub sec_nonce: SecretKey,
+	/// store my outputs between invocations
+	pub output_ids: Vec<Identifier>,
+	/// store my inputs
+	pub input_ids: Vec<Identifier>,
+	/// store the calculated fee
+	pub fee: u64,
+}
+
+impl Context {
+	/// Create a new context with defaults
+	pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey) -> Context {
+		Context {
+			sec_key: sec_key,
+			sec_nonce: aggsig::create_secnonce(secp).unwrap(),
+			input_ids: vec![],
+			output_ids: vec![],
+			fee: 0,
+		}
+	}
+}
+
+impl Context {
+	/// Tracks an output contributing to my excess value (if it needs to
+	/// be kept between invocations
+	pub fn add_output(&mut self, output_id: &Identifier) {
+		self.output_ids.push(output_id.clone());
+	}
+
+	/// Returns all stored outputs
+	pub fn get_outputs(&self) -> Vec<Identifier> {
+		self.output_ids.clone()
+	}
+
+	/// Tracks IDs of my inputs into the transaction
+	/// be kept between invocations
+	pub fn add_input(&mut self, input_id: &Identifier) {
+		self.input_ids.push(input_id.clone());
+	}
+
+	/// Returns all stored input identifiers
+	pub fn get_inputs(&self) -> Vec<Identifier> {
+		self.input_ids.clone()
+	}
+
+	/// Returns private key, private nonce
+	pub fn get_private_keys(&self) -> (SecretKey, SecretKey) {
+		(self.sec_key.clone(), self.sec_nonce.clone())
+	}
+
+	/// Returns public key, public nonce
+	pub fn get_public_keys(&self, secp: &Secp256k1) -> (PublicKey, PublicKey) {
+		(
+			PublicKey::from_secret_key(secp, &self.sec_key).unwrap(),
+			PublicKey::from_secret_key(secp, &self.sec_nonce).unwrap(),
+		)
+	}
+}
diff --git a/wallet/src/info.rs b/wallet/src/info.rs
index 190d576b3..b3de38ee5 100644
--- a/wallet/src/info.rs
+++ b/wallet/src/info.rs
@@ -13,10 +13,10 @@
 // limitations under the License.
 
 use checker;
-use keychain::Keychain;
 use core::core::amount_to_hr_string;
-use types::{OutputStatus, WalletConfig, WalletData, WalletInfo};
+use keychain::Keychain;
 use prettytable;
+use types::{OutputStatus, WalletConfig, WalletData, WalletInfo};
 
 pub fn show_info(config: &WalletConfig, keychain: &Keychain) {
 	let wallet_info = retrieve_info(config, keychain);
diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs
index 432c3d478..35d0c1fda 100644
--- a/wallet/src/lib.rs
+++ b/wallet/src/lib.rs
@@ -41,31 +41,28 @@ extern crate router;
 extern crate tokio_core;
 extern crate tokio_retry;
 
-#[macro_use]
-extern crate lazy_static;
-
 extern crate grin_api as api;
 extern crate grin_core as core;
 extern crate grin_keychain as keychain;
 extern crate grin_util as util;
 
 pub mod checker;
-mod handlers;
-mod outputs;
-mod info;
-pub mod receiver;
-mod sender;
-pub mod types;
-mod restore;
 pub mod client;
-pub mod server;
-pub mod libwallet;
 pub mod grinwallet;
+mod handlers;
+mod info;
+pub mod libwallet;
+mod outputs;
+pub mod receiver;
+mod restore;
+mod sender;
+pub mod server;
+pub mod types;
 
-pub use outputs::show_outputs;
 pub use info::{retrieve_info, show_info};
+pub use outputs::show_outputs;
 pub use receiver::WalletReceiver;
+pub use restore::restore;
 pub use sender::{issue_burn_tx, issue_send_tx};
 pub use types::{BlockFees, CbData, Error, ErrorKind, WalletConfig, WalletInfo,
                 WalletReceiveRequest, WalletSeed};
-pub use restore::restore;
diff --git a/wallet/src/libwallet/aggsig.rs b/wallet/src/libwallet/aggsig.rs
index f5353b5d6..cbea06d8e 100644
--- a/wallet/src/libwallet/aggsig.rs
+++ b/wallet/src/libwallet/aggsig.rs
@@ -11,9 +11,8 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-/// Aggsig library definitions
-use std::collections::HashMap;
-
+//! Aggsig helper functions used in transaction creation.. should be only
+//! interface into the underlying secp library
 use keychain::Keychain;
 use keychain::blind::BlindingFactor;
 use keychain::extkey::Identifier;
@@ -22,253 +21,38 @@ use util::kernel_sig_msg;
 use util::secp::key::{PublicKey, SecretKey};
 use util::secp::pedersen::Commitment;
 use util::secp::{self, aggsig, Message, Secp256k1, Signature};
-use uuid::Uuid;
 
-#[derive(Clone, Debug)]
-/// Holds the context for a single aggsig transaction
-pub struct Context {
-	/// Transaction ID
-	pub transaction_id: Uuid,
-	/// Secret key (of which public is shared)
-	pub sec_key: SecretKey,
-	/// Secret nonce (of which public is shared)
-	/// (basically a SecretKey)
-	pub sec_nonce: SecretKey,
-	/// If I'm the sender, store change key
-	/// TODO: remove in favor of outputs below
-	pub change_key: Option<Identifier>,
-	/// store my outputs between invocations
-	pub output_ids: Vec<Identifier>,
-	/// store my inputs
-	pub input_ids: Vec<Identifier>,
-	/// store the calculated fee
-	pub fee: u64,
+/// exports a secure nonce guaranteed to be usable
+/// in aggsig creation
+pub fn create_secnonce(secp: &Secp256k1) -> Result<SecretKey, Error> {
+	let nonce = aggsig::export_secnonce_single(secp)?;
+	Ok(nonce)
 }
 
-/*impl Context {
-	/// Create a new context with defaults
-	pub fn new(
-		secp: &secp::Secp256k1,
-		sec_key: SecretKey,
-	) -> Context {
-		Context {
-			sec_key: sec_key,
-			sec_nonce: aggsig::export_secnonce_single(secp).unwrap(),
-			change_key: None,
-			input_ids: vec![],
-			output_ids: vec![],
-			fee: 0,
-		},
-}*/
+/// Calculate a partial sig
+pub fn calculate_partial_sig(
+	secp: &Secp256k1,
+	sec_key: &SecretKey,
+	sec_nonce: &SecretKey,
+	nonce_sum: &PublicKey,
+	fee: u64,
+	lock_height: u64,
+) -> Result<Signature, Error> {
+	// Add public nonces kR*G + kS*G
+	let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height))?;
 
-#[derive(Clone, Debug)]
-/// Holds many contexts, to support multiple transactions hitting a wallet
-/// receiver at once
-/// TODO: Remove context manager in favour of context.. keeping multiple
-/// transactions separate is a wallet-specific concern
-pub struct ContextManager {
-	contexts: HashMap<Uuid, Context>,
+	//Now calculate signature using message M=fee, nonce in e=nonce_sum
+	let sig = aggsig::sign_single(
+		secp,
+		&msg,
+		sec_key,
+		Some(sec_nonce),
+		Some(nonce_sum),
+		Some(nonce_sum),
+	)?;
+	Ok(sig)
 }
 
-impl ContextManager {
-	/// Create
-	pub fn new() -> ContextManager {
-		ContextManager {
-			contexts: HashMap::new(),
-		}
-	}
-
-	/// Creates a context for a transaction id if required
-	/// otherwise does nothing
-	pub fn create_context(
-		&mut self,
-		secp: &secp::Secp256k1,
-		transaction_id: &Uuid,
-		sec_key: SecretKey,
-	) -> Context {
-		if !self.contexts.contains_key(transaction_id) {
-			self.contexts.insert(
-				transaction_id.clone(),
-				Context {
-					sec_key: sec_key,
-					transaction_id: transaction_id.clone(),
-					sec_nonce: aggsig::export_secnonce_single(secp).unwrap(),
-					change_key: None,
-					input_ids: vec![],
-					output_ids: vec![],
-					fee: 0,
-				},
-			);
-		}
-		self.get_context(transaction_id)
-	}
-
-	/// Retrieve a context by transaction id
-	pub fn get_context(&self, transaction_id: &Uuid) -> Context {
-		self.contexts.get(&transaction_id).unwrap().clone()
-	}
-
-	/// Save context
-	pub fn save_context(&mut self, c: Context) {
-		self.contexts.insert(c.transaction_id.clone(), c);
-	}
-}
-
-impl Context {
-	/// Tracks an output contributing to my excess value (if it needs to
-	/// be kept between invocations
-	pub fn add_output(&mut self, output_id: &Identifier) {
-		self.output_ids.push(output_id.clone());
-	}
-
-	/// Returns all stored outputs
-	pub fn get_outputs(&self) -> Vec<Identifier> {
-		self.output_ids.clone()
-	}
-
-	/// Tracks IDs of my inputs into the transaction
-	/// be kept between invocations
-	pub fn add_input(&mut self, input_id: &Identifier) {
-		self.input_ids.push(input_id.clone());
-	}
-
-	/// Returns all stored input identifiers
-	pub fn get_inputs(&self) -> Vec<Identifier> {
-		self.input_ids.clone()
-	}
-
-	/// Returns private key, private nonce
-	pub fn get_private_keys(&self) -> (SecretKey, SecretKey) {
-		(self.sec_key.clone(), self.sec_nonce.clone())
-	}
-
-	/// Returns public key, public nonce
-	pub fn get_public_keys(&self, secp: &Secp256k1) -> (PublicKey, PublicKey) {
-		(
-			PublicKey::from_secret_key(secp, &self.sec_key).unwrap(),
-			PublicKey::from_secret_key(secp, &self.sec_nonce).unwrap(),
-		)
-	}
-
-	/// Note 'secnonce' here is used to perform the signature, while 'pubnonce'
-	/// just allows you to provide a custom public nonce to include while
-	/// calculating e nonce_sum is the sum used to decide whether secnonce
-	/// should be inverted during sig time
-	pub fn sign_single(
-		&self,
-		secp: &Secp256k1,
-		msg: &Message,
-		secnonce: Option<&SecretKey>,
-		pubnonce: Option<&PublicKey>,
-		nonce_sum: Option<&PublicKey>,
-	) -> Result<Signature, Error> {
-		let sig = aggsig::sign_single(secp, msg, &self.sec_key, secnonce, pubnonce, nonce_sum)?;
-		Ok(sig)
-	}
-
-	//Verifies other final sig corresponds with what we're expecting
-	pub fn verify_final_sig_build_msg(
-		&self,
-		secp: &Secp256k1,
-		sig: &Signature,
-		pubkey: &PublicKey,
-		fee: u64,
-		lock_height: u64,
-	) -> bool {
-		let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height)).unwrap();
-		verify_single(secp, sig, &msg, None, pubkey, true)
-	}
-
-	//Verifies other party's sig corresponds with what we're expecting
-	pub fn verify_partial_sig(
-		&self,
-		secp: &Secp256k1,
-		sig: &Signature,
-		other_pub_nonce: &PublicKey,
-		pubkey: &PublicKey,
-		fee: u64,
-		lock_height: u64,
-	) -> bool {
-		let (_, sec_nonce) = self.get_private_keys();
-		let mut nonce_sum = other_pub_nonce.clone();
-		let _ = nonce_sum.add_exp_assign(secp, &sec_nonce);
-		let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height)).unwrap();
-
-		verify_single(secp, sig, &msg, Some(&nonce_sum), pubkey, true)
-	}
-
-	///TODO: Remove when below is integrated
-	pub fn calculate_partial_sig(
-		&self,
-		secp: &Secp256k1,
-		other_pub_nonce: &PublicKey,
-		fee: u64,
-		lock_height: u64,
-	) -> Result<Signature, Error> {
-		// Add public nonces kR*G + kS*G
-		let (_, sec_nonce) = self.get_private_keys();
-		let mut nonce_sum = other_pub_nonce.clone();
-		let _ = nonce_sum.add_exp_assign(secp, &sec_nonce);
-		let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height))?;
-
-		//Now calculate signature using message M=fee, nonce in e=nonce_sum
-		self.sign_single(
-			secp,
-			&msg,
-			Some(&sec_nonce),
-			Some(&nonce_sum),
-			Some(&nonce_sum),
-		)
-	}
-
-	pub fn calculate_partial_sig_with_nonce_sum(
-		&self,
-		secp: &Secp256k1,
-		nonce_sum: &PublicKey,
-		fee: u64,
-		lock_height: u64,
-	) -> Result<Signature, Error> {
-		// Add public nonces kR*G + kS*G
-		let (_, sec_nonce) = self.get_private_keys();
-		let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height))?;
-
-		//Now calculate signature using message M=fee, nonce in e=nonce_sum
-		self.sign_single(
-			secp,
-			&msg,
-			Some(&sec_nonce),
-			Some(&nonce_sum),
-			Some(&nonce_sum),
-		)
-	}
-
-	/// Helper function to calculate final signature
-	pub fn calculate_final_sig(
-		&self,
-		secp: &Secp256k1,
-		part_sigs: Vec<&Signature>,
-		nonce_sum: &PublicKey,
-	) -> Result<Signature, Error> {
-		// Add public nonces kR*G + kS*G
-		let sig = aggsig::add_signatures_single(&secp, part_sigs, &nonce_sum)?;
-		Ok(sig)
-	}
-
-	/// Helper function to calculate final public key
-	pub fn calculate_final_pubkey(
-		&self,
-		secp: &Secp256k1,
-		their_public_key: &PublicKey,
-	) -> Result<PublicKey, Error> {
-		let (our_sec_key, _) = self.get_private_keys();
-		let mut pk_sum = their_public_key.clone();
-		let _ = pk_sum.add_exp_assign(secp, &our_sec_key);
-		Ok(pk_sum)
-	}
-}
-
-// Contextless functions
-
 /// Verifies a partial sig given all public nonces used in the round
 pub fn verify_partial_sig(
 	secp: &Secp256k1,
@@ -277,9 +61,12 @@ pub fn verify_partial_sig(
 	pubkey: &PublicKey,
 	fee: u64,
 	lock_height: u64,
-) -> bool {
-	let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height)).unwrap();
-	verify_single(secp, sig, &msg, Some(&pub_nonce_sum), pubkey, true)
+) -> Result<(), Error> {
+	let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height))?;
+	if !verify_single(secp, sig, &msg, Some(&pub_nonce_sum), pubkey, true) {
+		return Err(Error::Signature("Signature validation error".to_string()));
+	}
+	Ok(())
 }
 
 /// Just a simple sig, creates its own nonce, etc
@@ -300,11 +87,14 @@ pub fn verify_single_from_commit(
 	sig: &Signature,
 	msg: &Message,
 	commit: &Commitment,
-) -> bool {
+) -> Result<(), Error> {
 	// Extract the pubkey, unfortunately we need this hack for now, (we just hope
 	// one is valid)
-	let pubkey = commit.to_pubkey(secp).unwrap();
-	aggsig::verify_single(secp, &sig, &msg, None, &pubkey, false)
+	let pubkey = commit.to_pubkey(secp)?;
+	if !verify_single(secp, sig, &msg, None, &pubkey, false) {
+		return Err(Error::Signature("Signature validation error".to_string()));
+	}
+	Ok(())
 }
 
 /// Verify a sig, with built message
@@ -314,12 +104,15 @@ pub fn verify_sig_build_msg(
 	pubkey: &PublicKey,
 	fee: u64,
 	lock_height: u64,
-) -> bool {
-	let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height)).unwrap();
-	verify_single(secp, sig, &msg, None, pubkey, true)
+) -> Result<(), Error> {
+	let msg = secp::Message::from_slice(&kernel_sig_msg(fee, lock_height))?;
+	if !verify_single(secp, sig, &msg, None, pubkey, true) {
+		return Err(Error::Signature("Signature validation error".to_string()));
+	}
+	Ok(())
 }
 
-//Verifies an aggsig signature
+/// Verifies an aggsig signature
 pub fn verify_single(
 	secp: &Secp256k1,
 	sig: &Signature,
diff --git a/wallet/src/libwallet/blind.rs b/wallet/src/libwallet/blind.rs
deleted file mode 100644
index bbf33b375..000000000
--- a/wallet/src/libwallet/blind.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Grin Developers
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Stub while figuring out wallet redesign
diff --git a/wallet/src/libwallet/build.rs b/wallet/src/libwallet/build.rs
index 71f91dab5..f9534f442 100644
--- a/wallet/src/libwallet/build.rs
+++ b/wallet/src/libwallet/build.rs
@@ -27,12 +27,12 @@
 
 use util::{kernel_sig_msg, secp};
 
-use core::core::{Input, Output, OutputFeatures, ProofMessageElements, Transaction, TxKernel};
 use core::core::hash::Hash;
 use core::core::pmmr::MerkleProof;
-use libwallet::{aggsig, proof};
+use core::core::{Input, Output, OutputFeatures, ProofMessageElements, Transaction, TxKernel};
 use keychain;
 use keychain::{BlindSum, BlindingFactor, Identifier, Keychain};
+use libwallet::{aggsig, proof};
 use util::LOGGER;
 
 /// Context information available to transaction combinators.
@@ -167,7 +167,8 @@ pub fn with_offset(offset: BlindingFactor) -> Box<Append> {
 }
 
 /// Sets an initial transaction to add to when building a new transaction.
-/// We currently only support building a tx with a single kernel with build::transaction()
+/// We currently only support building a tx with a single kernel with
+/// build::transaction()
 pub fn initial_tx(mut tx: Transaction) -> Box<Append> {
 	assert_eq!(tx.kernels.len(), 1);
 	let kern = tx.kernels.remove(0);
diff --git a/wallet/src/libwallet/error.rs b/wallet/src/libwallet/error.rs
index 0c4e6c871..1b1c9695a 100644
--- a/wallet/src/libwallet/error.rs
+++ b/wallet/src/libwallet/error.rs
@@ -14,16 +14,34 @@
 
 //! Wallet lib errors
 
-use util::secp;
+use core::core::transaction;
 use keychain::{self, extkey};
+use util::secp;
 
-#[derive(PartialEq, Eq, Clone, Debug)]
+#[derive(Fail, PartialEq, Clone, Debug)]
+/// Libwallet error types
 pub enum Error {
+	/// SECP error
+	#[fail(display = "Secp Error")]
 	Secp(secp::Error),
+	/// Keychain error
+	#[fail(display = "Keychain Error")]
 	Keychain(keychain::Error),
+	/// Extended key error
+	#[fail(display = "Extended Key Error")]
 	ExtendedKey(extkey::Error),
-	Transaction(String),
+	/// Transaction error
+	#[fail(display = "Transaction Error")]
+	Transaction(transaction::Error),
+	/// Signature error
+	#[fail(display = "Signature Error")]
+	Signature(String),
+	/// Rangeproof error
+	#[fail(display = "Rangeproof Error")]
 	RangeProof(String),
+	/// Fee error
+	#[fail(display = "Fee Error")]
+	Fee(String),
 }
 
 impl From<secp::Error> for Error {
@@ -43,18 +61,9 @@ impl From<keychain::Error> for Error {
 		Error::Keychain(e)
 	}
 }
-/*impl error::Error for Error {
-	fn description(&self) -> &str {
-		match *self {
-			_ => "some kind of wallet lib error",
-		}
+
+impl From<transaction::Error> for Error {
+	fn from(e: transaction::Error) -> Error {
+		Error::Transaction(e)
 	}
 }
-
-impl fmt::Display for Error {
-	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-		match *self {
-			_ => write!(f, "some kind of wallet lib error"),
-		}
-	}
-}*/
diff --git a/wallet/src/libwallet/mod.rs b/wallet/src/libwallet/mod.rs
index f2987ebb7..2bb863bc5 100644
--- a/wallet/src/libwallet/mod.rs
+++ b/wallet/src/libwallet/mod.rs
@@ -21,10 +21,9 @@
 #![deny(unused_mut)]
 #![warn(missing_docs)]
 
-pub mod error;
 pub mod aggsig;
-pub mod blind;
+pub mod build;
+pub mod error;
 pub mod proof;
 pub mod reward;
-pub mod build;
 pub mod transaction;
diff --git a/wallet/src/libwallet/proof.rs b/wallet/src/libwallet/proof.rs
index 73934db66..aada38291 100644
--- a/wallet/src/libwallet/proof.rs
+++ b/wallet/src/libwallet/proof.rs
@@ -14,16 +14,16 @@
 
 //! Rangeproof library functions
 
+use blake2;
 use keychain::Keychain;
-use util::secp::pedersen::{Commitment, ProofInfo, ProofMessage, RangeProof};
-use util::secp::key::SecretKey;
-use util::secp::{self, Secp256k1};
-use util::logger::LOGGER;
 use keychain::extkey::Identifier;
 use libwallet::error::Error;
-use blake2;
+use util::logger::LOGGER;
+use util::secp::key::SecretKey;
+use util::secp::pedersen::{Commitment, ProofInfo, ProofMessage, RangeProof};
+use util::secp::{self, Secp256k1};
 
-pub fn create_nonce(k: &Keychain, commit: &Commitment) -> SecretKey {
+fn create_nonce(k: &Keychain, commit: &Commitment) -> Result<SecretKey, Error> {
 	// hash(commit|masterkey) as nonce
 	let root_key = k.root_key_id().to_bytes();
 	let res = blake2::blake2b::blake2b(32, &commit.0, &root_key);
@@ -32,7 +32,12 @@ pub fn create_nonce(k: &Keychain, commit: &Commitment) -> SecretKey {
 	for i in 0..res.len() {
 		ret_val[i] = res[i];
 	}
-	SecretKey::from_slice(k.secp(), &ret_val).unwrap()
+	match SecretKey::from_slice(k.secp(), &ret_val) {
+		Ok(sk) => Ok(sk),
+		Err(e) => Err(Error::RangeProof(
+			format!("Unable to create nonce: {:?}", e).to_string(),
+		)),
+	}
 }
 
 /// So we want this to take an opaque structure that can be called
@@ -48,7 +53,7 @@ pub fn create(
 ) -> Result<RangeProof, Error> {
 	let commit = k.commit(amount, key_id)?;
 	let skey = k.derived_key(key_id)?;
-	let nonce = create_nonce(k, &commit);
+	let nonce = create_nonce(k, &commit)?;
 	if msg.len() == 0 {
 		return Ok(k.secp().bullet_proof(amount, skey, nonce, extra_data, None));
 	} else {
@@ -63,6 +68,7 @@ pub fn create(
 		.bullet_proof(amount, skey, nonce, extra_data, Some(msg)));
 }
 
+/// Verify a proof
 pub fn verify(
 	secp: &Secp256k1,
 	commit: Commitment,
@@ -76,6 +82,7 @@ pub fn verify(
 	}
 }
 
+/// Rewind a rangeproof to retrieve the amount
 pub fn rewind(
 	k: &Keychain,
 	key_id: &Identifier,
@@ -84,7 +91,7 @@ pub fn rewind(
 	proof: RangeProof,
 ) -> Result<ProofInfo, Error> {
 	let skey = k.derived_key(key_id)?;
-	let nonce = create_nonce(k, &commit);
+	let nonce = create_nonce(k, &commit)?;
 	let proof_message = k.secp()
 		.unwind_bullet_proof(commit, skey, nonce, extra_data, proof);
 	let proof_info = match proof_message {
diff --git a/wallet/src/libwallet/reward.rs b/wallet/src/libwallet/reward.rs
index 33c7e88be..63ac2f0f8 100644
--- a/wallet/src/libwallet/reward.rs
+++ b/wallet/src/libwallet/reward.rs
@@ -12,16 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-/// Builds the blinded output and related signature proof for the block
-/// reward.
-
+//! Builds the blinded output and related signature proof for the block
+//! reward.
 use keychain;
 
-use core::core::{Output, OutputFeatures, ProofMessageElements, TxKernel};
 use core::consensus::reward;
-use libwallet::{aggsig, proof};
-use libwallet::error::Error;
 use core::core::KernelFeatures;
+use core::core::{Output, OutputFeatures, ProofMessageElements, TxKernel};
+use libwallet::error::Error;
+use libwallet::{aggsig, proof};
 use util::{kernel_sig_msg, secp, static_secp_instance, LOGGER};
 
 /// output a reward output
diff --git a/wallet/src/libwallet/transaction.rs b/wallet/src/libwallet/transaction.rs
index 94175565a..cb0b344f3 100644
--- a/wallet/src/libwallet/transaction.rs
+++ b/wallet/src/libwallet/transaction.rs
@@ -17,17 +17,17 @@
 use rand::thread_rng;
 use uuid::Uuid;
 
+use core::consensus;
 use core::core::{amount_to_hr_string, Committed, Transaction};
 use keychain::{BlindSum, BlindingFactor, Keychain};
+use libwallet::error::Error;
 use libwallet::{aggsig, build};
-//TODO: Remove these from here, replace with libwallet error
-use types::{tx_fee, Error, ErrorKind};
 
 use util::secp::Signature;
 use util::secp::key::{PublicKey, SecretKey};
 use util::{secp, LOGGER};
 
-use failure::ResultExt;
+const DEFAULT_BASE_FEE: u64 = consensus::MILLI_GRIN;
 
 /// Public data for each participant in the slate
 
@@ -114,8 +114,7 @@ impl Slate {
 		if self.tx.kernels.len() != 0 {
 			elems.insert(0, build::initial_tx(self.tx.clone()));
 		}
-		let (tx, blind) =
-			build::partial_transaction(elems, &keychain).context(ErrorKind::Keychain)?;
+		let (tx, blind) = build::partial_transaction(elems, &keychain)?;
 		self.tx = tx;
 		Ok(blind)
 	}
@@ -125,14 +124,15 @@ impl Slate {
 	pub fn fill_round_1(
 		&mut self,
 		keychain: &Keychain,
-		context_manager: &mut aggsig::ContextManager,
+		sec_key: &mut SecretKey,
+		sec_nonce: &SecretKey,
 		participant_id: usize,
 	) -> Result<(), Error> {
 		// Whoever does this first generates the offset
 		if self.tx.offset == BlindingFactor::zero() {
-			self.generate_offset(keychain, context_manager)?;
+			self.generate_offset(keychain, sec_key)?;
 		}
-		self.add_participant_info(keychain, context_manager, participant_id, None)?;
+		self.add_participant_info(keychain, &sec_key, &sec_nonce, participant_id, None)?;
 		Ok(())
 	}
 
@@ -140,20 +140,20 @@ impl Slate {
 	pub fn fill_round_2(
 		&mut self,
 		keychain: &Keychain,
-		context_manager: &mut aggsig::ContextManager,
+		sec_key: &SecretKey,
+		sec_nonce: &SecretKey,
 		participant_id: usize,
 	) -> Result<(), Error> {
 		self.check_fees()?;
 		self.verify_part_sigs(keychain.secp())?;
-		let context = context_manager.get_context(&self.id);
-		let sig_part = context
-			.calculate_partial_sig_with_nonce_sum(
-				keychain.secp(),
-				&self.pub_nonce_sum(keychain.secp()),
-				self.fee,
-				self.lock_height,
-			)
-			.unwrap();
+		let sig_part = aggsig::calculate_partial_sig(
+			keychain.secp(),
+			sec_key,
+			sec_nonce,
+			&self.pub_nonce_sum(keychain.secp())?,
+			self.fee,
+			self.lock_height,
+		)?;
 		self.participant_data[participant_id].part_sig = Some(sig_part);
 		Ok(())
 	}
@@ -167,21 +167,27 @@ impl Slate {
 	}
 
 	/// Return the sum of public nonces
-	fn pub_nonce_sum(&self, secp: &secp::Secp256k1) -> PublicKey {
+	fn pub_nonce_sum(&self, secp: &secp::Secp256k1) -> Result<PublicKey, Error> {
 		let pub_nonces = self.participant_data
 			.iter()
 			.map(|p| &p.public_nonce)
 			.collect();
-		PublicKey::from_combination(secp, pub_nonces).unwrap()
+		match PublicKey::from_combination(secp, pub_nonces) {
+			Ok(k) => Ok(k),
+			Err(e) => Err(Error::Secp(e)),
+		}
 	}
 
 	/// Return the sum of public blinding factors
-	fn pub_blind_sum(&self, secp: &secp::Secp256k1) -> PublicKey {
+	fn pub_blind_sum(&self, secp: &secp::Secp256k1) -> Result<PublicKey, Error> {
 		let pub_blinds = self.participant_data
 			.iter()
 			.map(|p| &p.public_blind_excess)
 			.collect();
-		PublicKey::from_combination(secp, pub_blinds).unwrap()
+		match PublicKey::from_combination(secp, pub_blinds) {
+			Ok(k) => Ok(k),
+			Err(e) => Err(Error::Secp(e)),
+		}
 	}
 
 	/// Return vector of all partial sigs
@@ -199,14 +205,14 @@ impl Slate {
 	fn add_participant_info(
 		&mut self,
 		keychain: &Keychain,
-		context_manager: &aggsig::ContextManager,
+		sec_key: &SecretKey,
+		sec_nonce: &SecretKey,
 		id: usize,
 		part_sig: Option<Signature>,
 	) -> Result<(), Error> {
-		let context = context_manager.get_context(&self.id);
-
 		// Add our public key and nonce to the slate
-		let (pub_key, pub_nonce) = context.get_public_keys(keychain.secp());
+		let pub_key = PublicKey::from_secret_key(keychain.secp(), &sec_key)?;
+		let pub_nonce = PublicKey::from_secret_key(keychain.secp(), &sec_nonce)?;
 		self.participant_data.push(ParticipantData {
 			id: id as u64,
 			public_blind_excess: pub_key,
@@ -219,27 +225,22 @@ impl Slate {
 
 	/// Somebody involved needs to generate an offset with their private key
 	/// For now, we'll have the transaction initiator be responsible for it
-	/// Return offset private key
+	/// Return offset private key for the participant to use later in the
+	/// transaction
 	fn generate_offset(
 		&mut self,
 		keychain: &Keychain,
-		context_manager: &mut aggsig::ContextManager,
+		sec_key: &mut SecretKey,
 	) -> Result<(), Error> {
 		// Generate a random kernel offset here
 		// and subtract it from the blind_sum so we create
 		// the aggsig context with the "split" key
-		let mut context = context_manager.get_context(&self.id);
 		self.tx.offset =
 			BlindingFactor::from_secret_key(SecretKey::new(&keychain.secp(), &mut thread_rng()));
-		let blind_offset = keychain
-			.blind_sum(&BlindSum::new()
-				.add_blinding_factor(BlindingFactor::from_secret_key(context.sec_key))
-				.sub_blinding_factor(self.tx.offset))
-			.unwrap();
-		context.sec_key = blind_offset
-			.secret_key(&keychain.secp())
-			.context(ErrorKind::Keychain)?;
-		context_manager.save_context(context);
+		let blind_offset = keychain.blind_sum(&BlindSum::new()
+			.add_blinding_factor(BlindingFactor::from_secret_key(sec_key.clone()))
+			.sub_blinding_factor(self.tx.offset))?;
+		*sec_key = blind_offset.secret_key(&keychain.secp())?;
 		Ok(())
 	}
 
@@ -255,23 +256,19 @@ impl Slate {
 			None,
 		);
 		if fee > self.tx.fee() {
-			return Err(ErrorKind::FeeDispute {
-				sender_fee: self.tx.fee(),
-				recipient_fee: fee,
-			})?;
+			return Err(Error::Fee(
+				format!("Fee Dispute Error: {}, {}", self.tx.fee(), fee,).to_string(),
+			));
 		}
 
 		if fee > self.amount + self.fee {
-			info!(
-				LOGGER,
+			let reason = format!(
 				"Rejected the transfer because transaction fee ({}) exceeds received amount ({}).",
 				amount_to_hr_string(fee),
 				amount_to_hr_string(self.amount + self.fee)
 			);
-			return Err(ErrorKind::FeeExceedsAmount {
-				sender_amount: self.amount + self.fee,
-				recipient_fee: fee,
-			})?;
+			info!(LOGGER, "{}", reason);
+			return Err(Error::Fee(reason.to_string()));
 		}
 
 		Ok(())
@@ -282,18 +279,14 @@ impl Slate {
 		// collect public nonces
 		for p in self.participant_data.iter() {
 			if p.is_complete() {
-				if aggsig::verify_partial_sig(
+				aggsig::verify_partial_sig(
 					secp,
 					p.part_sig.as_ref().unwrap(),
-					&self.pub_nonce_sum(secp),
+					&self.pub_nonce_sum(secp)?,
 					&p.public_blind_excess,
 					self.fee,
 					self.lock_height,
-				) == false
-				{
-					error!(LOGGER, "Partial Sig invalid.");
-					return Err(ErrorKind::Signature("Partial Sig invalid."))?;
-				}
+				)?;
 			}
 		}
 		Ok(())
@@ -320,27 +313,21 @@ impl Slate {
 		self.verify_part_sigs(keychain.secp())?;
 
 		let part_sigs = self.part_sigs();
-		let pub_nonce_sum = self.pub_nonce_sum(keychain.secp());
-		let final_pubkey = self.pub_blind_sum(keychain.secp());
+		let pub_nonce_sum = self.pub_nonce_sum(keychain.secp())?;
+		let final_pubkey = self.pub_blind_sum(keychain.secp())?;
 		// get the final signature
-		let final_sig =
-			aggsig::add_signatures(&keychain.secp(), part_sigs, &pub_nonce_sum).unwrap();
+		let final_sig = aggsig::add_signatures(&keychain.secp(), part_sigs, &pub_nonce_sum)?;
 
 		// Calculate the final public key (for our own sanity check)
 
 		// Check our final sig verifies
-		let res = aggsig::verify_sig_build_msg(
+		aggsig::verify_sig_build_msg(
 			&keychain.secp(),
 			&final_sig,
 			&final_pubkey,
 			self.fee,
 			self.lock_height,
-		);
-
-		if !res {
-			error!(LOGGER, "Final aggregated signature invalid.");
-			return Err(ErrorKind::Signature("Final aggregated signature invalid."))?;
-		}
+		)?;
 
 		Ok(final_sig)
 	}
@@ -361,24 +348,20 @@ impl Slate {
 		let final_excess = {
 			// TODO - do we need to verify rangeproofs here?
 			for x in &final_tx.outputs {
-				x.verify_proof().context(ErrorKind::Transaction)?;
+				x.verify_proof()?;
 			}
 
 			// sum the input/output commitments on the final tx
 			let overage = final_tx.fee() as i64;
-			let tx_excess = final_tx
-				.sum_commitments(overage, None)
-				.context(ErrorKind::Transaction)?;
+			let tx_excess = final_tx.sum_commitments(overage, None)?;
 
 			// subtract the kernel_excess (built from kernel_offset)
 			let offset_excess = keychain
 				.secp()
-				.commit(0, kernel_offset.secret_key(&keychain.secp()).unwrap())
-				.unwrap();
+				.commit(0, kernel_offset.secret_key(&keychain.secp())?)?;
 			keychain
 				.secp()
-				.commit_sum(vec![tx_excess], vec![offset_excess])
-				.context(ErrorKind::Transaction)?
+				.commit_sum(vec![tx_excess], vec![offset_excess])?
 		};
 
 		// update the tx kernel to reflect the offset excess and sig
@@ -388,14 +371,22 @@ impl Slate {
 
 		// confirm the kernel verifies successfully before proceeding
 		debug!(LOGGER, "Validating final transaction");
-		final_tx.kernels[0]
-			.verify()
-			.context(ErrorKind::Transaction)?;
+		final_tx.kernels[0].verify()?;
 
 		// confirm the overall transaction is valid (including the updated kernel)
-		let _ = final_tx.validate().context(ErrorKind::Transaction)?;
+		let _ = final_tx.validate()?;
 
 		self.tx = final_tx;
 		Ok(())
 	}
 }
+
+/// Transaction fee calculation
+pub fn tx_fee(input_len: usize, output_len: usize, proof_len: usize, base_fee: Option<u64>) -> u64 {
+	let use_base_fee = match base_fee {
+		Some(bf) => bf,
+		None => DEFAULT_BASE_FEE,
+	};
+
+	(Transaction::weight(input_len, output_len, proof_len) as u64) * use_base_fee
+}
diff --git a/wallet/src/outputs.rs b/wallet/src/outputs.rs
index dae082c20..a3c554b38 100644
--- a/wallet/src/outputs.rs
+++ b/wallet/src/outputs.rs
@@ -13,12 +13,12 @@
 // limitations under the License.
 
 use checker;
-use keychain::Keychain;
 use core::core;
-use types::{OutputStatus, WalletConfig, WalletData};
+use keychain::Keychain;
 use prettytable;
-use term;
 use std::io::prelude::*;
+use term;
+use types::{OutputStatus, WalletConfig, WalletData};
 
 pub fn show_outputs(config: &WalletConfig, keychain: &Keychain, show_spent: bool) {
 	let root_key_id = keychain.root_key_id();
diff --git a/wallet/src/receiver.rs b/wallet/src/receiver.rs
index cec358e6e..37e5bdfd2 100644
--- a/wallet/src/receiver.rs
+++ b/wallet/src/receiver.rs
@@ -21,16 +21,16 @@ use iron::Handler;
 use iron::prelude::*;
 use iron::status;
 use serde_json;
-use std::sync::{Arc, RwLock};
 
 use api;
 use core::consensus::reward;
 use core::core::{Output, TxKernel};
 use core::global;
 use failure::Fail;
+use failure::ResultExt;
 use grinwallet::{keys, selection};
 use keychain::Keychain;
-use libwallet::{aggsig, reward, transaction};
+use libwallet::{reward, transaction};
 use types::*;
 use util::LOGGER;
 
@@ -40,28 +40,24 @@ pub struct TxWrapper {
 	pub tx_hex: String,
 }
 
-lazy_static! {
-	/// Static reference to aggsig context (temporary while wallet is being refactored)
-	pub static ref AGGSIG_CONTEXT_MANAGER:Arc<RwLock<aggsig::ContextManager>>
-		= Arc::new(RwLock::new(aggsig::ContextManager::new()));
-}
-
 fn handle_send(
 	config: &WalletConfig,
 	keychain: &Keychain,
-	context_manager: &mut aggsig::ContextManager,
 	slate: &mut transaction::Slate,
 ) -> Result<(), Error> {
 	// create an output using the amount in the slate
-	let (_, receiver_create_fn) =
-		selection::build_recipient_output_with_slate(config, keychain, context_manager, slate)
-			.unwrap();
+	let (_, mut context, receiver_create_fn) =
+		selection::build_recipient_output_with_slate(config, keychain, slate).unwrap();
 
 	// fill public keys
-	let _ = slate.fill_round_1(&keychain, context_manager, 1)?;
+	let _ = slate
+		.fill_round_1(&keychain, &mut context.sec_key, &context.sec_nonce, 1)
+		.context(ErrorKind::LibWalletError)?;
 
 	// perform partial sig
-	let _ = slate.fill_round_2(&keychain, context_manager, 1)?;
+	let _ = slate
+		.fill_round_2(&keychain, &context.sec_key, &context.sec_nonce, 1)
+		.context(ErrorKind::LibWalletError)?;
 
 	// Save output in wallet
 	let _ = receiver_create_fn();
@@ -82,8 +78,7 @@ impl Handler for WalletReceiver {
 		let struct_body = req.get::<bodyparser::Struct<transaction::Slate>>();
 
 		if let Ok(Some(mut slate)) = struct_body {
-			let mut acm = AGGSIG_CONTEXT_MANAGER.write().unwrap();
-			let _ = handle_send(&self.config, &self.keychain, &mut acm, &mut slate)
+			let _ = handle_send(&self.config, &self.keychain, &mut slate)
 				.map_err(|e| {
 					error!(
 						LOGGER,
diff --git a/wallet/src/restore.rs b/wallet/src/restore.rs
index 2e3efe1a6..f0d0292e3 100644
--- a/wallet/src/restore.rs
+++ b/wallet/src/restore.rs
@@ -11,18 +11,18 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+use api;
+use byteorder::{BigEndian, ByteOrder};
+use core::core::transaction::ProofMessageElements;
+use core::global;
 use failure::{Fail, ResultExt};
 use keychain::{Identifier, Keychain};
+use libwallet::proof;
+use types::{Error, ErrorKind, MerkleProofWrapper, OutputData, OutputStatus, WalletConfig,
+            WalletData};
 use util;
 use util::LOGGER;
 use util::secp::pedersen;
-use api;
-use core::global;
-use core::core::transaction::ProofMessageElements;
-use types::{Error, ErrorKind, MerkleProofWrapper, OutputData, OutputStatus, WalletConfig,
-            WalletData};
-use byteorder::{BigEndian, ByteOrder};
-use libwallet::proof;
 
 pub fn get_chain_height(config: &WalletConfig) -> Result<u64, Error> {
 	let url = format!("{}/v1/chain", config.check_node_api_http_addr);
@@ -105,8 +105,17 @@ fn find_outputs_with_key(
 	keychain: &Keychain,
 	outputs: Vec<api::OutputPrintable>,
 	found_key_index: &mut Vec<u32>,
-) -> Vec<
-	(
+) -> Vec<(
+	pedersen::Commitment,
+	Identifier,
+	u32,
+	u64,
+	u64,
+	u64,
+	bool,
+	Option<MerkleProofWrapper>,
+)> {
+	let mut wallet_outputs: Vec<(
 		pedersen::Commitment,
 		Identifier,
 		u32,
@@ -115,20 +124,7 @@ fn find_outputs_with_key(
 		u64,
 		bool,
 		Option<MerkleProofWrapper>,
-	),
-> {
-	let mut wallet_outputs: Vec<
-		(
-			pedersen::Commitment,
-			Identifier,
-			u32,
-			u64,
-			u64,
-			u64,
-			bool,
-			Option<MerkleProofWrapper>,
-		),
-	> = Vec::new();
+	)> = Vec::new();
 
 	let max_derivations = 1_000_000;
 
diff --git a/wallet/src/sender.rs b/wallet/src/sender.rs
index e37f47234..bc81103d3 100644
--- a/wallet/src/sender.rs
+++ b/wallet/src/sender.rs
@@ -20,7 +20,7 @@ use core::ser;
 use failure::ResultExt;
 use grinwallet::selection;
 use keychain::{Identifier, Keychain};
-use libwallet::{aggsig, build};
+use libwallet::{build, transaction};
 use receiver::TxWrapper;
 use types::*;
 use util;
@@ -50,9 +50,6 @@ pub fn issue_send_tx(
 
 	checker::refresh_outputs(config, keychain)?;
 
-	// Create a new aggsig context
-	let mut context_manager = aggsig::ContextManager::new();
-
 	// Get lock height
 	let chain_tip = checker::get_tip_from_node(config)?;
 	let current_height = chain_tip.height;
@@ -61,17 +58,16 @@ pub fn issue_send_tx(
 
 	let lock_height = current_height;
 
-	// Sender selects outputs into a new slate and save our corresponding IDs in
-	// their transaction context. The secret key in our transaction context will be
+	// Sender selects outputs into a new slate and save our corresponding keyss in
+	// a transaction context. The secret key in our transaction context will be
 	// randomly selected. This returns the public slate, and a closure that locks
 	// our inputs and outputs once we're convinced the transaction exchange went
 	// according to plan
 	// This function is just a big helper to do all of that, in theory
 	// this process can be split up in any way
-	let (mut slate, sender_lock_fn) = selection::build_send_tx_slate(
+	let (mut slate, mut context, sender_lock_fn) = selection::build_send_tx_slate(
 		config,
 		keychain,
-		&mut context_manager,
 		2,
 		amount,
 		current_height,
@@ -85,7 +81,7 @@ pub fn issue_send_tx(
 	// the offset in the slate's transaction kernel, and adds our public key
 	// information to the slate
 	let _ = slate
-		.fill_round_1(keychain, &mut context_manager, 0)
+		.fill_round_1(keychain, &mut context.sec_key, &context.sec_nonce, 0)
 		.unwrap();
 
 	let url = format!("{}/v1/receive/transaction", &dest);
@@ -112,10 +108,12 @@ pub fn issue_send_tx(
 		}
 	};
 
-	let _ = slate.fill_round_2(keychain, &mut context_manager, 0)?;
+	let _ = slate
+		.fill_round_2(keychain, &context.sec_key, &context.sec_nonce, 0)
+		.context(ErrorKind::LibWalletError)?;
 
 	// Final transaction can be built by anyone at this stage
-	slate.finalize(keychain)?;
+	slate.finalize(keychain).context(ErrorKind::LibWalletError)?;
 
 	// So let's post it
 	let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
@@ -130,7 +128,7 @@ pub fn issue_send_tx(
 	}
 	api::client::post(url.as_str(), &TxWrapper { tx_hex: tx_hex }).context(ErrorKind::Node)?;
 
-	// All good so, lock our outputs
+	// All good so, lock our inputs
 	sender_lock_fn()?;
 	Ok(())
 }
@@ -165,8 +163,9 @@ pub fn issue_burn_tx(
 
 	debug!(LOGGER, "selected some coins - {}", coins.len());
 
-	let fee = tx_fee(coins.len(), 2, selection::coins_proof_count(&coins), None);
-	let (mut parts, _) = selection::inputs_and_change(&coins, config, keychain, amount, fee)?;
+	let fee = transaction::tx_fee(coins.len(), 2, selection::coins_proof_count(&coins), None);
+	let (mut parts, _) =
+		selection::inputs_and_change(&coins, config, keychain, current_height, amount, fee)?;
 
 	// add burn output and fees
 	parts.push(build::output(amount - fee, Identifier::zero()));
diff --git a/wallet/src/server.rs b/wallet/src/server.rs
index afa552612..20a38b59d 100644
--- a/wallet/src/server.rs
+++ b/wallet/src/server.rs
@@ -13,8 +13,8 @@
 // limitations under the License.
 
 use api::ApiServer;
-use keychain::Keychain;
 use handlers::CoinbaseHandler;
+use keychain::Keychain;
 use receiver::WalletReceiver;
 use types::WalletConfig;
 use util::LOGGER;
diff --git a/wallet/src/types.rs b/wallet/src/types.rs
index 8ee5aa52a..552b1e4e9 100644
--- a/wallet/src/types.rs
+++ b/wallet/src/types.rs
@@ -32,8 +32,6 @@ use tokio_retry::strategy::FibonacciBackoff;
 
 use failure::{Backtrace, Context, Fail, ResultExt};
 
-use core::consensus;
-use core::core::Transaction;
 use core::core::hash::Hash;
 use core::core::pmmr::MerkleProof;
 use keychain;
@@ -45,18 +43,6 @@ const BCK_FILE: &'static str = "wallet.bck";
 const LOCK_FILE: &'static str = "wallet.lock";
 const SEED_FILE: &'static str = "wallet.seed";
 
-const DEFAULT_BASE_FEE: u64 = consensus::MILLI_GRIN;
-
-/// Transaction fee calculation
-pub fn tx_fee(input_len: usize, output_len: usize, proof_len: usize, base_fee: Option<u64>) -> u64 {
-	let use_base_fee = match base_fee {
-		Some(bf) => bf,
-		None => DEFAULT_BASE_FEE,
-	};
-
-	(Transaction::weight(input_len, output_len, proof_len) as u64) * use_base_fee
-}
-
 #[derive(Debug)]
 pub struct Error {
 	inner: Context<ErrorKind>,
@@ -87,6 +73,9 @@ pub enum ErrorKind {
 	#[fail(display = "Secp error")]
 	Secp,
 
+	#[fail(display = "LibWallet error")]
+	LibWalletError,
+
 	#[fail(display = "Wallet data error: {}", _0)]
 	WalletData(&'static str),
 
diff --git a/wallet/tests/common/mod.rs b/wallet/tests/common/mod.rs
index a79d86b4c..459328d4e 100644
--- a/wallet/tests/common/mod.rs
+++ b/wallet/tests/common/mod.rs
@@ -42,16 +42,21 @@ pub fn refresh_output_state_local(
 	chain: &chain::Chain,
 ) -> Result<(), Error> {
 	let wallet_outputs = checker::map_wallet_outputs(config, keychain)?;
-	let chain_outputs: Vec<api::Output> = wallet_outputs
+	let chain_outputs: Vec<Option<api::Output>> = wallet_outputs
 		.keys()
 		.map(|k| match get_output_local(chain, &k) {
-			Err(e) => panic!(e),
-			Ok(k) => k,
+			Err(_) => None,
+			Ok(k) => Some(k),
 		})
 		.collect();
 	let mut api_outputs: HashMap<pedersen::Commitment, api::Output> = HashMap::new();
 	for out in chain_outputs {
-		api_outputs.insert(out.commit.commit(), out);
+		match out {
+			Some(o) => {
+				api_outputs.insert(o.commit.commit(), o);
+			}
+			None => {}
+		}
 	}
 	checker::apply_api_outputs(config, &wallet_outputs, &api_outputs)?;
 	Ok(())
diff --git a/wallet/tests/libwallet.rs b/wallet/tests/libwallet.rs
index 48bc7b9b8..f23f4c73a 100644
--- a/wallet/tests/libwallet.rs
+++ b/wallet/tests/libwallet.rs
@@ -24,7 +24,7 @@ use keychain::{BlindSum, BlindingFactor, Keychain};
 use util::secp::key::{PublicKey, SecretKey};
 use util::secp::pedersen::ProofMessage;
 use util::{kernel_sig_msg, secp};
-use uuid::Uuid;
+use wallet::grinwallet::sigcontext;
 use wallet::libwallet::{aggsig, proof};
 
 use rand::thread_rng;
@@ -33,11 +33,6 @@ use rand::thread_rng;
 fn aggsig_sender_receiver_interaction() {
 	let sender_keychain = Keychain::from_random_seed().unwrap();
 	let receiver_keychain = Keychain::from_random_seed().unwrap();
-	let mut sender_aggsig_cm = aggsig::ContextManager::new();
-	let mut receiver_aggsig_cm = aggsig::ContextManager::new();
-
-	// tx identifier for wallet interaction
-	let tx_id = Uuid::new_v4();
 
 	// Calculate the kernel excess here for convenience.
 	// Normally this would happen during transaction building.
@@ -63,8 +58,10 @@ fn aggsig_sender_receiver_interaction() {
 			.unwrap()
 	};
 
+	let s_cx;
+	let mut rx_cx;
 	// sender starts the tx interaction
-	let (sender_pub_excess, sender_pub_nonce) = {
+	let (sender_pub_excess, _sender_pub_nonce) = {
 		let keychain = sender_keychain.clone();
 
 		let skey = keychain
@@ -80,25 +77,39 @@ fn aggsig_sender_receiver_interaction() {
 
 		let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
 
-		let cx = sender_aggsig_cm.create_context(&keychain.secp(), &tx_id, blind);
-		cx.get_public_keys(&keychain.secp())
+		s_cx = sigcontext::Context::new(&keychain.secp(), blind);
+		s_cx.get_public_keys(&keychain.secp())
 	};
 
+	let pub_nonce_sum;
 	// receiver receives partial tx
-	let (receiver_pub_excess, receiver_pub_nonce, sig_part) = {
+	let (receiver_pub_excess, _receiver_pub_nonce, rx_sig_part) = {
 		let keychain = receiver_keychain.clone();
 		let key_id = keychain.derive_key_id(1).unwrap();
 
 		// let blind = blind_sum.secret_key(&keychain.secp())?;
 		let blind = keychain.derived_key(&key_id).unwrap();
 
-		let mut cx = receiver_aggsig_cm.create_context(&keychain.secp(), &tx_id, blind);
-		let (pub_excess, pub_nonce) = cx.get_public_keys(&keychain.secp());
-		cx.add_output(&key_id);
+		rx_cx = sigcontext::Context::new(&keychain.secp(), blind);
+		let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
+		rx_cx.add_output(&key_id);
 
-		let sig_part = cx.calculate_partial_sig(&keychain.secp(), &sender_pub_nonce, 0, 0)
-			.unwrap();
-		receiver_aggsig_cm.save_context(cx);
+		pub_nonce_sum = PublicKey::from_combination(
+			keychain.secp(),
+			vec![
+				&s_cx.get_public_keys(keychain.secp()).1,
+				&rx_cx.get_public_keys(keychain.secp()).1,
+			],
+		).unwrap();
+
+		let sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&rx_cx.sec_key,
+			&rx_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
+		).unwrap();
 		(pub_excess, pub_nonce, sig_part)
 	};
 
@@ -106,66 +117,74 @@ fn aggsig_sender_receiver_interaction() {
 	// received in the response back from the receiver
 	{
 		let keychain = sender_keychain.clone();
-		let cx = sender_aggsig_cm.get_context(&tx_id);
-		let sig_verifies = cx.verify_partial_sig(
+		let sig_verifies = aggsig::verify_partial_sig(
 			&keychain.secp(),
-			&sig_part,
-			&receiver_pub_nonce,
+			&rx_sig_part,
+			&pub_nonce_sum,
 			&receiver_pub_excess,
 			0,
 			0,
 		);
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// now sender signs with their key
 	let sender_sig_part = {
 		let keychain = sender_keychain.clone();
-		let cx = sender_aggsig_cm.get_context(&tx_id);
-		cx.calculate_partial_sig(&keychain.secp(), &receiver_pub_nonce, 0, 0)
-			.unwrap()
+		let sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&s_cx.sec_key,
+			&s_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
+		).unwrap();
+		sig_part
 	};
 
 	// check the receiver can verify the partial signature
 	// received by the sender
 	{
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
-		let sig_verifies = cx.verify_partial_sig(
+		let sig_verifies = aggsig::verify_partial_sig(
 			&keychain.secp(),
 			&sender_sig_part,
-			&sender_pub_nonce,
+			&pub_nonce_sum,
 			&sender_pub_excess,
 			0,
 			0,
 		);
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// Receiver now builds final signature from sender and receiver parts
 	let (final_sig, final_pubkey) = {
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
 
-		// Receiver recreates their partial sig (we do not maintain state from earlier)
-		let our_sig_part = cx.calculate_partial_sig(&keychain.secp(), &sender_pub_nonce, 0, 0)
-			.unwrap();
-
-		let combined_nonces = PublicKey::from_combination(
-			keychain.secp(),
-			vec![&sender_pub_nonce, &cx.get_public_keys(keychain.secp()).1],
+		let our_sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&rx_cx.sec_key,
+			&rx_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
 		).unwrap();
 
 		// Receiver now generates final signature from the two parts
-		let final_sig = cx.calculate_final_sig(
+		let final_sig = aggsig::add_signatures(
 			&keychain.secp(),
 			vec![&sender_sig_part, &our_sig_part],
-			&combined_nonces,
+			&pub_nonce_sum,
 		).unwrap();
 
 		// Receiver calculates the final public key (to verify sig later)
-		let final_pubkey = cx.calculate_final_pubkey(&keychain.secp(), &sender_pub_excess)
-			.unwrap();
+		let final_pubkey = PublicKey::from_combination(
+			keychain.secp(),
+			vec![
+				&s_cx.get_public_keys(keychain.secp()).0,
+				&rx_cx.get_public_keys(keychain.secp()).0,
+			],
+		).unwrap();
 
 		(final_sig, final_pubkey)
 	};
@@ -173,12 +192,11 @@ fn aggsig_sender_receiver_interaction() {
 	// Receiver checks the final signature verifies
 	{
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
 
 		// Receiver check the final signature verifies
 		let sig_verifies =
-			cx.verify_final_sig_build_msg(&keychain.secp(), &final_sig, &final_pubkey, 0, 0);
-		assert!(sig_verifies);
+			aggsig::verify_sig_build_msg(&keychain.secp(), &final_sig, &final_pubkey, 0, 0);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// Check we can verify the sig using the kernel excess
@@ -190,7 +208,7 @@ fn aggsig_sender_receiver_interaction() {
 		let sig_verifies =
 			aggsig::verify_single_from_commit(&keychain.secp(), &final_sig, &msg, &kernel_excess);
 
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 }
 
@@ -198,11 +216,6 @@ fn aggsig_sender_receiver_interaction() {
 fn aggsig_sender_receiver_interaction_offset() {
 	let sender_keychain = Keychain::from_random_seed().unwrap();
 	let receiver_keychain = Keychain::from_random_seed().unwrap();
-	let mut sender_aggsig_cm = aggsig::ContextManager::new();
-	let mut receiver_aggsig_cm = aggsig::ContextManager::new();
-
-	// tx identifier for wallet interaction
-	let tx_id = Uuid::new_v4();
 
 	// This is the kernel offset that we use to split the key
 	// Summing these at the block level prevents the
@@ -236,8 +249,10 @@ fn aggsig_sender_receiver_interaction_offset() {
 			.unwrap()
 	};
 
+	let s_cx;
+	let mut rx_cx;
 	// sender starts the tx interaction
-	let (sender_pub_excess, sender_pub_nonce) = {
+	let (sender_pub_excess, _sender_pub_nonce) = {
 		let keychain = sender_keychain.clone();
 
 		let skey = keychain
@@ -256,24 +271,38 @@ fn aggsig_sender_receiver_interaction_offset() {
 
 		let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
 
-		let cx = sender_aggsig_cm.create_context(&keychain.secp(), &tx_id, blind);
-		cx.get_public_keys(&keychain.secp())
+		s_cx = sigcontext::Context::new(&keychain.secp(), blind);
+		s_cx.get_public_keys(&keychain.secp())
 	};
 
 	// receiver receives partial tx
-	let (receiver_pub_excess, receiver_pub_nonce, sig_part) = {
+	let pub_nonce_sum;
+	let (receiver_pub_excess, _receiver_pub_nonce, sig_part) = {
 		let keychain = receiver_keychain.clone();
 		let key_id = keychain.derive_key_id(1).unwrap();
 
 		let blind = keychain.derived_key(&key_id).unwrap();
 
-		let mut cx = receiver_aggsig_cm.create_context(&keychain.secp(), &tx_id, blind);
-		let (pub_excess, pub_nonce) = cx.get_public_keys(&keychain.secp());
-		cx.add_output(&key_id);
+		rx_cx = sigcontext::Context::new(&keychain.secp(), blind);
+		let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
+		rx_cx.add_output(&key_id);
 
-		let sig_part = cx.calculate_partial_sig(&keychain.secp(), &sender_pub_nonce, 0, 0)
-			.unwrap();
-		receiver_aggsig_cm.save_context(cx);
+		pub_nonce_sum = PublicKey::from_combination(
+			keychain.secp(),
+			vec![
+				&s_cx.get_public_keys(keychain.secp()).1,
+				&rx_cx.get_public_keys(keychain.secp()).1,
+			],
+		).unwrap();
+
+		let sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&rx_cx.sec_key,
+			&rx_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
+		).unwrap();
 		(pub_excess, pub_nonce, sig_part)
 	};
 
@@ -281,66 +310,73 @@ fn aggsig_sender_receiver_interaction_offset() {
 	// received in the response back from the receiver
 	{
 		let keychain = sender_keychain.clone();
-		let cx = sender_aggsig_cm.get_context(&tx_id);
-		let sig_verifies = cx.verify_partial_sig(
+		let sig_verifies = aggsig::verify_partial_sig(
 			&keychain.secp(),
 			&sig_part,
-			&receiver_pub_nonce,
+			&pub_nonce_sum,
 			&receiver_pub_excess,
 			0,
 			0,
 		);
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// now sender signs with their key
 	let sender_sig_part = {
 		let keychain = sender_keychain.clone();
-		let cx = sender_aggsig_cm.get_context(&tx_id);
-		cx.calculate_partial_sig(&keychain.secp(), &receiver_pub_nonce, 0, 0)
-			.unwrap()
+		let sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&s_cx.sec_key,
+			&s_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
+		).unwrap();
+		sig_part
 	};
 
 	// check the receiver can verify the partial signature
 	// received by the sender
 	{
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
-		let sig_verifies = cx.verify_partial_sig(
+		let sig_verifies = aggsig::verify_partial_sig(
 			&keychain.secp(),
 			&sender_sig_part,
-			&sender_pub_nonce,
+			&pub_nonce_sum,
 			&sender_pub_excess,
 			0,
 			0,
 		);
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// Receiver now builds final signature from sender and receiver parts
 	let (final_sig, final_pubkey) = {
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
-
-		// Receiver recreates their partial sig (we do not maintain state from earlier)
-		let our_sig_part = cx.calculate_partial_sig(&keychain.secp(), &sender_pub_nonce, 0, 0)
-			.unwrap();
-
-		let combined_nonces = PublicKey::from_combination(
-			keychain.secp(),
-			vec![&sender_pub_nonce, &cx.get_public_keys(keychain.secp()).1],
+		let our_sig_part = aggsig::calculate_partial_sig(
+			&keychain.secp(),
+			&rx_cx.sec_key,
+			&rx_cx.sec_nonce,
+			&pub_nonce_sum,
+			0,
+			0,
 		).unwrap();
 
 		// Receiver now generates final signature from the two parts
-		let final_sig = cx.calculate_final_sig(
+		let final_sig = aggsig::add_signatures(
 			&keychain.secp(),
 			vec![&sender_sig_part, &our_sig_part],
-			&combined_nonces,
+			&pub_nonce_sum,
 		).unwrap();
 
 		// Receiver calculates the final public key (to verify sig later)
-		let final_pubkey = cx.calculate_final_pubkey(&keychain.secp(), &sender_pub_excess)
-			.unwrap();
+		let final_pubkey = PublicKey::from_combination(
+			keychain.secp(),
+			vec![
+				&s_cx.get_public_keys(keychain.secp()).0,
+				&rx_cx.get_public_keys(keychain.secp()).0,
+			],
+		).unwrap();
 
 		(final_sig, final_pubkey)
 	};
@@ -348,12 +384,11 @@ fn aggsig_sender_receiver_interaction_offset() {
 	// Receiver checks the final signature verifies
 	{
 		let keychain = receiver_keychain.clone();
-		let cx = receiver_aggsig_cm.get_context(&tx_id);
 
 		// Receiver check the final signature verifies
 		let sig_verifies =
-			cx.verify_final_sig_build_msg(&keychain.secp(), &final_sig, &final_pubkey, 0, 0);
-		assert!(sig_verifies);
+			aggsig::verify_sig_build_msg(&keychain.secp(), &final_sig, &final_pubkey, 0, 0);
+		assert!(!sig_verifies.is_err());
 	}
 
 	// Check we can verify the sig using the kernel excess
@@ -365,7 +400,7 @@ fn aggsig_sender_receiver_interaction_offset() {
 		let sig_verifies =
 			aggsig::verify_single_from_commit(&keychain.secp(), &final_sig, &msg, &kernel_excess);
 
-		assert!(sig_verifies);
+		assert!(!sig_verifies.is_err());
 	}
 }
 
diff --git a/wallet/tests/transaction.rs b/wallet/tests/transaction.rs
index 202570852..fe887e0bb 100644
--- a/wallet/tests/transaction.rs
+++ b/wallet/tests/transaction.rs
@@ -35,7 +35,6 @@ use core::global::ChainTypes;
 use core::{global, pow};
 use util::LOGGER;
 use wallet::grinwallet::selection;
-use wallet::libwallet::aggsig;
 
 fn clean_output_dir(test_dir: &str) {
 	let _ = fs::remove_dir_all(test_dir);
@@ -57,7 +56,7 @@ fn setup(test_dir: &str, chain_dir: &str) -> Chain {
 
 /// Build and test new version of sending API
 #[test]
-fn build_transaction_2() {
+fn build_transaction() {
 	let chain = setup("test_output", "build_transaction_2/.grin");
 	let wallet1 = common::create_wallet("test_output/build_transaction_2/wallet1");
 	let wallet2 = common::create_wallet("test_output/build_transaction_2/wallet2");
@@ -68,6 +67,7 @@ fn build_transaction_2() {
 	// Get lock height
 	let chain_tip = chain.head().unwrap();
 	let amount = 300_000_000_000;
+	let min_confirmations = 3;
 
 	// ensure outputs we're selecting are up to date
 	let res = common::refresh_output_state_local(&wallet1.0, &wallet1.1, &chain);
@@ -77,23 +77,20 @@ fn build_transaction_2() {
 	}
 
 	// TRANSACTION WORKFLOW STARTS HERE
-	// Sender creates a new aggsig context
-	let mut sender_context_manager = aggsig::ContextManager::new();
 	// Sender selects outputs into a new slate and save our corresponding IDs in
-	// their transaction context. The secret key in our transaction context will be
+	// a transaction context. The secret key in our transaction context will be
 	// randomly selected. This returns the public slate, and a closure that locks
 	// our inputs and outputs once we're convinced the transaction exchange went
 	// according to plan
 	// This function is just a big helper to do all of that, in theory
 	// this process can be split up in any way
-	let (mut slate, sender_lock_fn) = selection::build_send_tx_slate(
+	let (mut slate, mut sender_context, sender_lock_fn) = selection::build_send_tx_slate(
 		&wallet1.0,
 		&wallet1.1,
-		&mut sender_context_manager,
 		2,
 		amount,
 		chain_tip.height,
-		3,
+		min_confirmations,
 		chain_tip.height,
 		1000,
 		true,
@@ -103,36 +100,44 @@ fn build_transaction_2() {
 	// the offset in the slate's transaction kernel, and adds our public key
 	// information to the slate
 	let _ = slate
-		.fill_round_1(&wallet1.1, &mut sender_context_manager, 0)
+		.fill_round_1(
+			&wallet1.1,
+			&mut sender_context.sec_key,
+			&sender_context.sec_nonce,
+			0,
+		)
 		.unwrap();
 
 	debug!(LOGGER, "Transaction Slate after step 1: sender initiation");
 	debug!(LOGGER, "-----------------------------------------");
 	debug!(LOGGER, "{:?}", slate);
 
-	// RECIPIENT (Handle sender initiation)
-	let mut recipient_context_manager = aggsig::ContextManager::new();
-
 	// Now, just like the sender did, recipient is going to select a target output,
 	// add it to the transaction, and keep track of the corresponding wallet
 	// Identifier Again, this is a helper to do that, which returns a closure that
 	// creates the output when we're satisified the process was successful
-	let (_, receiver_create_fn) = selection::build_recipient_output_with_slate(
-		&wallet2.0,
-		&wallet2.1,
-		&mut recipient_context_manager,
-		&mut slate,
-	).unwrap();
+	let (_, mut recp_context, receiver_create_fn) =
+		selection::build_recipient_output_with_slate(&wallet2.0, &wallet2.1, &mut slate).unwrap();
 
 	let _ = slate
-		.fill_round_1(&wallet2.1, &mut recipient_context_manager, 1)
+		.fill_round_1(
+			&wallet2.1,
+			&mut recp_context.sec_key,
+			&recp_context.sec_nonce,
+			1,
+		)
 		.unwrap();
 
 	// recipient can proceed to round 2 now
 	let _ = receiver_create_fn();
 
 	let _ = slate
-		.fill_round_2(&wallet2.1, &mut recipient_context_manager, 1)
+		.fill_round_2(
+			&wallet2.1,
+			&recp_context.sec_key,
+			&recp_context.sec_nonce,
+			1,
+		)
 		.unwrap();
 
 	debug!(
@@ -144,7 +149,12 @@ fn build_transaction_2() {
 
 	// SENDER Part 3: Sender confirmation
 	let _ = slate
-		.fill_round_2(&wallet1.1, &mut sender_context_manager, 0)
+		.fill_round_2(
+			&wallet1.1,
+			&sender_context.sec_key,
+			&sender_context.sec_nonce,
+			0,
+		)
 		.unwrap();
 
 	debug!(LOGGER, "PartialTx after step 3: sender confirmation");
@@ -167,7 +177,7 @@ fn build_transaction_2() {
 
 	// Insert this transaction into a new block, then mine till confirmation
 	common::award_block_to_wallet(&chain, vec![&slate.tx], &wallet1);
-	common::award_blocks_to_wallet(&chain, &wallet1, 3);
+	common::award_blocks_to_wallet(&chain, &wallet1, 5);
 
 	// Refresh wallets
 	let res = common::refresh_output_state_local(&wallet2.0, &wallet2.1, &chain);
@@ -175,8 +185,23 @@ fn build_transaction_2() {
 		panic!("Error refreshing output state for wallet: {:?}", e);
 	}
 
+	// check recipient wallet
 	let chain_tip = chain.head().unwrap();
 	let balances = common::get_wallet_balances(&wallet2.0, &wallet2.1, chain_tip.height).unwrap();
 
 	assert_eq!(balances.3, 300_000_000_000);
+
+	// check sender wallet
+	let res = common::refresh_output_state_local(&wallet1.0, &wallet1.1, &chain);
+	if let Err(e) = res {
+		panic!("Error refreshing output state for wallet: {:?}", e);
+	}
+	let balances = common::get_wallet_balances(&wallet1.0, &wallet1.1, chain_tip.height).unwrap();
+	println!("tip height: {:?}", chain_tip.height);
+	println!("Sender balances: {:?}", balances);
+	// num blocks * grins per block, and wallet1 mined the fee
+	assert_eq!(
+		balances.3,
+		(chain_tip.height - min_confirmations) * 60_000_000_000 - amount
+	);
 }