Skip to content

Commit

Permalink
Update the FFI Wallet container to use the Sqlite backends (#1088)
Browse files Browse the repository at this point in the history
Merge pull request #1088

This PR Updates the wallet container to accept all 4 storage backends
for the services it contains. This allows for the Wallet services that
require storage to be constructed with either types of backend.

The Wallet FFI now builds the Wallet container using the Sqlite
persistence backend.
  • Loading branch information
CjS77 committed Dec 3, 2019
2 parents 4f5686d + d64d69d commit c0a6762
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 60 deletions.
3 changes: 3 additions & 0 deletions base_layer/wallet/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::{
contacts_service::error::ContactsServiceError,
output_manager_service::error::OutputManagerError,
storage::database::DbKey,
transaction_service::error::TransactionServiceError,
Expand All @@ -31,6 +32,7 @@ use log::SetLoggerError;
use serde_json::Error as SerdeJsonError;
use tari_comms::{builder::CommsError, connection::NetAddressError, peer_manager::PeerManagerError};
use tari_p2p::initialization::CommsInitializationError;

#[derive(Debug, Error)]
pub enum WalletError {
CommsInitializationError(CommsInitializationError),
Expand All @@ -41,6 +43,7 @@ pub enum WalletError {
NetAddressError(NetAddressError),
WalletStorageError(WalletStorageError),
SetLoggerError(SetLoggerError),
ContactsServiceError(ContactsServiceError),
}

#[derive(Debug, Error)]
Expand Down
71 changes: 61 additions & 10 deletions base_layer/wallet/src/testnet_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{
contacts_service::storage::database::Contact,
contacts_service::storage::database::{Contact, ContactsBackend},
error::{WalletError, WalletStorageError},
output_manager_service::TxId,
output_manager_service::{
storage::{database::OutputManagerBackend, memory_db::OutputManagerMemoryDatabase},
TxId,
},
storage::{database::WalletBackend, memory_db::WalletMemoryDatabase},
transaction_service::storage::database::{CompletedTransaction, TransactionStatus},
transaction_service::storage::{
database::{CompletedTransaction, TransactionBackend, TransactionStatus},
memory_db::TransactionMemoryDatabase,
},
wallet::WalletConfig,
Wallet,
};

use crate::contacts_service::storage::memory_db::ContactsServiceMemoryDatabase;
use chrono::Utc;
use rand::{distributions::Alphanumeric, CryptoRng, OsRng, Rng, RngCore};
use std::{iter, sync::Arc, thread, time::Duration};
Expand Down Expand Up @@ -90,7 +98,11 @@ pub fn random_string(len: usize) -> String {
}

/// Create a wallet for testing purposes
pub fn create_wallet(secret_key: CommsSecretKey, net_address: String) -> Wallet<WalletMemoryDatabase> {
pub fn create_wallet(
secret_key: CommsSecretKey,
net_address: String,
) -> Wallet<WalletMemoryDatabase, TransactionMemoryDatabase, OutputManagerMemoryDatabase, ContactsServiceMemoryDatabase>
{
let runtime = Runtime::new().unwrap();
let factories = CryptoFactories::default();

Expand Down Expand Up @@ -131,11 +143,26 @@ pub fn create_wallet(secret_key: CommsSecretKey, net_address: String) -> Wallet<
factories,
};

Wallet::new(config, WalletMemoryDatabase::new(), runtime).expect("Could not create Wallet")
Wallet::new(
config,
runtime,
WalletMemoryDatabase::new(),
TransactionMemoryDatabase::new(),
OutputManagerMemoryDatabase::new(),
ContactsServiceMemoryDatabase::new(),
)
.expect("Could not create Wallet")
}

/// This function will generate a set of test data for the supplied wallet. Takes a few seconds to complete
pub fn generate_wallet_test_data<T: WalletBackend>(wallet: &mut Wallet<T>) -> Result<(), WalletError> {
pub fn generate_wallet_test_data<
T: WalletBackend,
U: TransactionBackend,
V: OutputManagerBackend,
W: ContactsBackend,
>(
wallet: &mut Wallet<T, U, V, W>,
) -> Result<(), WalletError> {
let rng = rand::OsRng::new().unwrap();
let factories = CryptoFactories::default();
let names = ["Alice", "Bob", "Carol", "Dave"];
Expand Down Expand Up @@ -281,7 +308,16 @@ pub fn generate_wallet_test_data<T: WalletBackend>(wallet: &mut Wallet<T>) -> Re
/// This function is only available for testing and development by the client of LibWallet. It simulates a this node,
/// who sent a transaction out, accepting a reply to the Pending Outbound Transaction. That transaction then becomes a
/// CompletedTransaction with the Broadcast status indicating it is in a base node Mempool but not yet mined
pub fn complete_sent_transaction<T: WalletBackend>(wallet: &mut Wallet<T>, tx_id: TxId) -> Result<(), WalletError> {
pub fn complete_sent_transaction<
T: WalletBackend,
U: TransactionBackend,
V: OutputManagerBackend,
W: ContactsBackend,
>(
wallet: &mut Wallet<T, U, V, W>,
tx_id: TxId,
) -> Result<(), WalletError>
{
let pending_outbound_tx = wallet
.runtime
.block_on(wallet.transaction_service.get_pending_outbound_transactions())?;
Expand Down Expand Up @@ -316,7 +352,14 @@ pub fn complete_sent_transaction<T: WalletBackend>(wallet: &mut Wallet<T>, tx_id

/// This function is only available for testing by the client of LibWallet. This function simulates an external
/// wallet sending a transaction to this wallet which will become a PendingInboundTransaction
pub fn receive_test_transaction<T: WalletBackend>(wallet: &mut Wallet<T>) -> Result<(), WalletError> {
pub fn receive_test_transaction<
T: WalletBackend,
U: TransactionBackend,
V: OutputManagerBackend,
W: ContactsBackend,
>(
wallet: &mut Wallet<T, U, V, W>,
) -> Result<(), WalletError> {
let mut rng = OsRng::new().unwrap();
let (_secret_key, public_key): (CommsSecretKey, CommsPublicKey) = PublicKey::random_keypair(&mut rng);

Expand All @@ -331,7 +374,11 @@ pub fn receive_test_transaction<T: WalletBackend>(wallet: &mut Wallet<T>) -> Res
Ok(())
}

pub fn broadcast_transaction<T: WalletBackend>(wallet: &mut Wallet<T>, tx_id: TxId) -> Result<(), WalletError> {
pub fn broadcast_transaction<T: WalletBackend, U: TransactionBackend, V: OutputManagerBackend, W: ContactsBackend>(
wallet: &mut Wallet<T, U, V, W>,
tx_id: TxId,
) -> Result<(), WalletError>
{
wallet
.runtime
.block_on(wallet.transaction_service.test_broadcast_transaction(tx_id))?;
Expand All @@ -343,7 +390,11 @@ pub fn broadcast_transaction<T: WalletBackend>(wallet: &mut Wallet<T>, tx_id: Tx
/// the event when a CompletedTransaction that is in the Broadcast status, is in a mempool but not mined, beocmes
/// mined/confirmed. After this function is called the status of the CompletedTransaction becomes `Mined` and the funds
/// that were pending become spent and available respectively.
pub fn mine_transaction<T: WalletBackend>(wallet: &mut Wallet<T>, tx_id: TxId) -> Result<(), WalletError> {
pub fn mine_transaction<T: WalletBackend, U: TransactionBackend, V: OutputManagerBackend, W: ContactsBackend>(
wallet: &mut Wallet<T, U, V, W>,
tx_id: TxId,
) -> Result<(), WalletError>
{
wallet
.runtime
.block_on(wallet.transaction_service.test_mine_transaction(tx_id))?;
Expand Down
52 changes: 35 additions & 17 deletions base_layer/wallet/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,18 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::{
contacts_service::{
handle::ContactsServiceHandle,
storage::memory_db::ContactsServiceMemoryDatabase,
ContactsServiceInitializer,
},
contacts_service::{handle::ContactsServiceHandle, storage::database::ContactsBackend, ContactsServiceInitializer},
error::WalletError,
output_manager_service::{
handle::OutputManagerHandle,
storage::memory_db::OutputManagerMemoryDatabase,
storage::database::OutputManagerBackend,
OutputManagerConfig,
OutputManagerServiceInitializer,
},
storage::database::{WalletBackend, WalletDatabase},
transaction_service::{
handle::TransactionServiceHandle,
storage::memory_db::TransactionMemoryDatabase,
storage::database::TransactionBackend,
TransactionServiceInitializer,
},
};
Expand All @@ -47,7 +43,7 @@ use log4rs::{
encode::pattern::PatternEncoder,
Handle as LogHandle,
};
use std::sync::Arc;
use std::{marker::PhantomData, sync::Arc};
use tari_comms::{
builder::CommsNode,
connection::{net_address::NetAddressWithStats, NetAddressesWithStats},
Expand Down Expand Up @@ -77,8 +73,12 @@ pub struct WalletConfig {

/// A structure containing the config and services that a Wallet application will require. This struct will start up all
/// the services and provide the APIs that applications will use to interact with the services
pub struct Wallet<T>
where T: WalletBackend
pub struct Wallet<T, U, V, W>
where
T: WalletBackend,
U: TransactionBackend + 'static,
V: OutputManagerBackend + 'static,
W: ContactsBackend + 'static,
{
pub comms: CommsNode,
pub dht_service: Dht,
Expand All @@ -89,12 +89,27 @@ where T: WalletBackend
pub db: WalletDatabase<T>,
pub runtime: Runtime,
pub log_handle: Option<LogHandle>,
_u: PhantomData<U>,
_v: PhantomData<V>,
_w: PhantomData<W>,
}

impl<T> Wallet<T>
where T: WalletBackend
impl<T, U, V, W> Wallet<T, U, V, W>
where
T: WalletBackend,
U: TransactionBackend + 'static,
V: OutputManagerBackend + 'static,
W: ContactsBackend + 'static,
{
pub fn new(config: WalletConfig, backend: T, runtime: Runtime) -> Result<Wallet<T>, WalletError> {
pub fn new(
config: WalletConfig,
runtime: Runtime,
wallet_backend: T,
transaction_backend: U,
output_manager_backend: V,
contacts_backend: W,
) -> Result<Wallet<T, U, V, W>, WalletError>
{
let mut log_handle = None;
if let Some(path) = config.logging_path {
let logfile = FileAppender::builder()
Expand Down Expand Up @@ -140,16 +155,16 @@ where T: WalletBackend
))
.add_initializer(OutputManagerServiceInitializer::new(
oms_config,
OutputManagerMemoryDatabase::new(),
output_manager_backend,
factories.clone(),
))
.add_initializer(TransactionServiceInitializer::new(
subscription_factory.clone(),
TransactionMemoryDatabase::new(),
transaction_backend,
comms.node_identity().clone(),
factories.clone(),
))
.add_initializer(ContactsServiceInitializer::new(ContactsServiceMemoryDatabase::new()))
.add_initializer(ContactsServiceInitializer::new(contacts_backend))
.finish();

let handles = runtime.block_on(fut).expect("Service initialization failed");
Expand All @@ -174,9 +189,12 @@ where T: WalletBackend
output_manager_service: output_manager_handle,
transaction_service: transaction_service_handle,
contacts_service: contacts_handle,
db: WalletDatabase::new(backend),
db: WalletDatabase::new(wallet_backend),
runtime,
log_handle,
_u: PhantomData,
_v: PhantomData,
_w: PhantomData,
})
}

Expand Down
45 changes: 39 additions & 6 deletions base_layer/wallet/tests/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ use tari_transactions::{tari_amount::MicroTari, types::CryptoFactories};
#[cfg(feature = "test_harness")]
use tari_wallet::testnet_utils::broadcast_transaction;
use tari_wallet::{
contacts_service::storage::database::Contact,
contacts_service::storage::{database::Contact, memory_db::ContactsServiceMemoryDatabase},
output_manager_service::storage::memory_db::OutputManagerMemoryDatabase,
storage::memory_db::WalletMemoryDatabase,
transaction_service::handle::TransactionEvent,
transaction_service::{handle::TransactionEvent, storage::memory_db::TransactionMemoryDatabase},
wallet::WalletConfig,
Wallet,
};
Expand Down Expand Up @@ -128,8 +129,24 @@ fn test_wallet() {
};
let runtime_node1 = Runtime::new().unwrap();
let runtime_node2 = Runtime::new().unwrap();
let mut alice_wallet = Wallet::new(config1, WalletMemoryDatabase::new(), runtime_node1).unwrap();
let bob_wallet = Wallet::new(config2, WalletMemoryDatabase::new(), runtime_node2).unwrap();
let mut alice_wallet = Wallet::new(
config1,
runtime_node1,
WalletMemoryDatabase::new(),
TransactionMemoryDatabase::new(),
OutputManagerMemoryDatabase::new(),
ContactsServiceMemoryDatabase::new(),
)
.unwrap();
let bob_wallet = Wallet::new(
config2,
runtime_node2,
WalletMemoryDatabase::new(),
TransactionMemoryDatabase::new(),
OutputManagerMemoryDatabase::new(),
ContactsServiceMemoryDatabase::new(),
)
.unwrap();

alice_wallet
.comms
Expand Down Expand Up @@ -235,7 +252,15 @@ fn test_data_generation() {
logging_path: None,
};

let mut wallet = Wallet::new(config, WalletMemoryDatabase::new(), runtime).unwrap();
let mut wallet = Wallet::new(
config,
runtime,
WalletMemoryDatabase::new(),
TransactionMemoryDatabase::new(),
OutputManagerMemoryDatabase::new(),
ContactsServiceMemoryDatabase::new(),
)
.unwrap();

generate_wallet_test_data(&mut wallet).unwrap();

Expand Down Expand Up @@ -318,7 +343,15 @@ fn test_test_harness() {
};

let runtime = Runtime::new().unwrap();
let mut alice_wallet = Wallet::new(config1, WalletMemoryDatabase::new(), runtime).unwrap();
let mut alice_wallet = Wallet::new(
config1,
runtime,
WalletMemoryDatabase::new(),
TransactionMemoryDatabase::new(),
OutputManagerMemoryDatabase::new(),
ContactsServiceMemoryDatabase::new(),
)
.unwrap();

let value = MicroTari::from(1000);
let (_utxo, uo1) = make_input(&mut rng, MicroTari(2500), &factories.commitment);
Expand Down
Loading

0 comments on commit c0a6762

Please sign in to comment.