Have monerod running in own container

This commit is contained in:
Philipp Hoenisch 2020-10-29 12:52:29 +11:00
parent 7b101a9c98
commit 0dcb4e56be
No known key found for this signature in database
GPG Key ID: E5F8E74C672BC666
2 changed files with 48 additions and 174 deletions

View File

@ -124,6 +124,12 @@ pub struct Args {
wallets: Vec<WalletArgs>,
}
#[derive(Debug)]
pub enum MoneroArgs {
MonerodArgs(MonerodArgs),
WalletArgs(WalletArgs),
}
#[derive(Debug, Clone)]
pub struct MonerodArgs {
pub regtest: bool,
@ -282,10 +288,7 @@ impl IntoIterator for Args {
args.push("/bin/bash".into());
args.push("-c".into());
let wallet_args: Vec<String> = self.wallets.iter().map(|wallet| wallet.args()).collect();
let wallet_args = wallet_args.join(" & ");
let cmd = format!("{} & {} ", self.monerod.args(), wallet_args);
let cmd = format!("{} ", self.monerod.args());
args.push(cmd);
args.into_iter()

View File

@ -27,7 +27,7 @@ pub mod rpc;
use anyhow::{anyhow, Result};
use serde::Deserialize;
use std::time::Duration;
use testcontainers::{clients::Cli, core::Port, Container, Docker};
use testcontainers::{clients::Cli, core::Port, Container, Docker, RunArgs};
use tokio::time;
use crate::{
@ -44,15 +44,9 @@ const BLOCK_TIME_SECS: u64 = 1;
/// Poll interval when checking if the wallet has synced with monerod.
const WAIT_WALLET_SYNC_MILLIS: u64 = 1000;
/// Wallet sub-account indices.
const ACCOUNT_INDEX_PRIMARY: u32 = 0;
#[derive(Copy, Clone, Debug)]
pub struct Monero {
monerod_rpc_port: u16,
miner_wallet_rpc_port: u16,
alice_wallet_rpc_port: u16,
bob_wallet_rpc_port: u16,
}
impl<'c> Monero {
@ -60,59 +54,18 @@ impl<'c> Monero {
pub fn new(cli: &'c Cli) -> Result<(Self, Container<'c, Cli, image::Monero>)> {
let monerod_rpc_port: u16 =
port_check::free_local_port().ok_or_else(|| anyhow!("Could not retrieve free port"))?;
let miner_wallet_rpc_port: u16 =
port_check::free_local_port().ok_or_else(|| anyhow!("Could not retrieve free port"))?;
let alice_wallet_rpc_port: u16 =
port_check::free_local_port().ok_or_else(|| anyhow!("Could not retrieve free port"))?;
let bob_wallet_rpc_port: u16 =
port_check::free_local_port().ok_or_else(|| anyhow!("Could not retrieve free port"))?;
let image = image::Monero::default()
.with_mapped_port(Port {
local: monerod_rpc_port,
internal: MONEROD_RPC_PORT,
})
.with_mapped_port(Port {
local: miner_wallet_rpc_port,
internal: MINER_WALLET_RPC_PORT,
})
.with_wallet("miner", MINER_WALLET_RPC_PORT)
.with_mapped_port(Port {
local: alice_wallet_rpc_port,
internal: ALICE_WALLET_RPC_PORT,
})
.with_wallet("alice", ALICE_WALLET_RPC_PORT)
.with_mapped_port(Port {
local: bob_wallet_rpc_port,
internal: BOB_WALLET_RPC_PORT,
})
.with_wallet("bob", BOB_WALLET_RPC_PORT);
let image = image::Monero::default().with_mapped_port(Port {
local: monerod_rpc_port,
internal: MONEROD_RPC_PORT,
});
println!("running image ...");
let docker = cli.run(image);
println!("image ran");
let run_args = RunArgs::default()
.with_name("monerod")
.with_network("monero");
let docker = cli.run_with_args(image, run_args);
Ok((
Self {
monerod_rpc_port,
miner_wallet_rpc_port,
alice_wallet_rpc_port,
bob_wallet_rpc_port,
},
docker,
))
}
pub fn miner_wallet_rpc_client(&self) -> wallet::Client {
wallet::Client::localhost(self.miner_wallet_rpc_port)
}
pub fn alice_wallet_rpc_client(&self) -> wallet::Client {
wallet::Client::localhost(self.alice_wallet_rpc_port)
}
pub fn bob_wallet_rpc_client(&self) -> wallet::Client {
wallet::Client::localhost(self.bob_wallet_rpc_port)
Ok((Self { monerod_rpc_port }, docker))
}
pub fn monerod_rpc_client(&self) -> monerod::Client {
@ -124,122 +77,40 @@ impl<'c> Monero {
/// sub-accounts, one for Alice and one for Bob. If alice/bob_funding is
/// some, the value needs to be > 0.
pub async fn init(&self, alice_funding: u64, bob_funding: u64) -> Result<()> {
let miner_wallet = self.miner_wallet_rpc_client();
let alice_wallet = self.alice_wallet_rpc_client();
let bob_wallet = self.bob_wallet_rpc_client();
let monerod = self.monerod_rpc_client();
miner_wallet.create_wallet("miner_wallet").await?;
alice_wallet.create_wallet("alice_wallet").await?;
bob_wallet.create_wallet("bob_wallet").await?;
let miner = self.get_address_miner().await?.address;
let alice = self.get_address_alice().await?.address;
let bob = self.get_address_bob().await?.address;
let _ = monerod.generate_blocks(70, &miner).await?;
self.wait_for_miner_wallet_block_height().await?;
if alice_funding > 0 {
self.fund_account(&alice, &miner, alice_funding).await?;
self.wait_for_alice_wallet_block_height().await?;
let balance = self.get_balance_alice().await?;
debug_assert!(balance == alice_funding);
}
if bob_funding > 0 {
self.fund_account(&bob, &miner, bob_funding).await?;
self.wait_for_bob_wallet_block_height().await?;
let balance = self.get_balance_bob().await?;
debug_assert!(balance == bob_funding);
}
let _ = tokio::spawn(mine(monerod.clone(), miner));
// let miner_wallet = self.miner_wallet_rpc_client();
// let alice_wallet = self.alice_wallet_rpc_client();
// let bob_wallet = self.bob_wallet_rpc_client();
// let monerod = self.monerod_rpc_client();
//
// miner_wallet.create_wallet("miner_wallet").await?;
// alice_wallet.create_wallet("alice_wallet").await?;
// bob_wallet.create_wallet("bob_wallet").await?;
//
// let miner = self.get_address_miner().await?.address;
// let alice = self.get_address_alice().await?.address;
// let bob = self.get_address_bob().await?.address;
//
// let _ = monerod.generate_blocks(70, &miner).await?;
// self.wait_for_miner_wallet_block_height().await?;
//
// if alice_funding > 0 {
// self.fund_account(&alice, &miner, alice_funding).await?;
// self.wait_for_alice_wallet_block_height().await?;
// let balance = self.get_balance_alice().await?;
// debug_assert!(balance == alice_funding);
// }
//
// if bob_funding > 0 {
// self.fund_account(&bob, &miner, bob_funding).await?;
// self.wait_for_bob_wallet_block_height().await?;
// let balance = self.get_balance_bob().await?;
// debug_assert!(balance == bob_funding);
// }
//
// let _ = tokio::spawn(mine(monerod.clone(), miner));
Ok(())
}
async fn fund_account(&self, address: &str, miner: &str, funding: u64) -> Result<()> {
let monerod = self.monerod_rpc_client();
self.transfer_from_primary(funding, address).await?;
let _ = monerod.generate_blocks(10, miner).await?;
self.wait_for_miner_wallet_block_height().await?;
Ok(())
}
async fn wait_for_miner_wallet_block_height(&self) -> Result<()> {
self.wait_for_wallet_height(self.miner_wallet_rpc_client())
.await
}
pub async fn wait_for_alice_wallet_block_height(&self) -> Result<()> {
self.wait_for_wallet_height(self.alice_wallet_rpc_client())
.await
}
pub async fn wait_for_bob_wallet_block_height(&self) -> Result<()> {
self.wait_for_wallet_height(self.bob_wallet_rpc_client())
.await
}
// It takes a little while for the wallet to sync with monerod.
async fn wait_for_wallet_height(&self, wallet: wallet::Client) -> Result<()> {
let monerod = self.monerod_rpc_client();
let height = monerod.get_block_count().await?;
while wallet.block_height().await?.height < height {
time::delay_for(Duration::from_millis(WAIT_WALLET_SYNC_MILLIS)).await;
}
Ok(())
}
/// Get addresses for the primary account.
async fn get_address_miner(&self) -> Result<GetAddress> {
let wallet = self.miner_wallet_rpc_client();
wallet.get_address(ACCOUNT_INDEX_PRIMARY).await
}
/// Get addresses for the Alice's account.
async fn get_address_alice(&self) -> Result<GetAddress> {
let wallet = self.alice_wallet_rpc_client();
wallet.get_address(ACCOUNT_INDEX_PRIMARY).await
}
/// Get addresses for the Bob's account.
async fn get_address_bob(&self) -> Result<GetAddress> {
let wallet = self.bob_wallet_rpc_client();
wallet.get_address(ACCOUNT_INDEX_PRIMARY).await
}
/// Gets the balance of Alice's account.
async fn get_balance_alice(&self) -> Result<u64> {
let wallet = self.alice_wallet_rpc_client();
wallet.get_balance(ACCOUNT_INDEX_PRIMARY).await
}
/// Gets the balance of Bob's account.
async fn get_balance_bob(&self) -> Result<u64> {
let wallet = self.bob_wallet_rpc_client();
wallet.get_balance(ACCOUNT_INDEX_PRIMARY).await
}
/// Transfers moneroj from the primary account.
async fn transfer_from_primary(&self, amount: u64, address: &str) -> Result<Transfer> {
let wallet = self.miner_wallet_rpc_client();
wallet
.transfer(ACCOUNT_INDEX_PRIMARY, amount, address)
.await
}
}
/// Mine a block ever BLOCK_TIME_SECS seconds.
async fn mine(monerod: monerod::Client, reward_address: String) -> Result<()> {
loop {
time::delay_for(Duration::from_secs(BLOCK_TIME_SECS)).await;
monerod.generate_blocks(1, &reward_address).await?;
}
}
// We should be able to use monero-rs for this but it does not include all