Skip to content
13 changes: 8 additions & 5 deletions masq/src/commands/configuration_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ impl ConfigurationCommand {
dump_parameter_line(
stream,
"Start block:",
&configuration.start_block.to_string(),
&configuration
.start_block_opt
.map(|m| m.separate_with_commas())
.unwrap_or_else(|| "[Latest]".to_string()),
);
Self::dump_value_list(stream, "Past neighbors:", &configuration.past_neighbors);
let payment_thresholds = Self::preprocess_combined_parameters({
Expand Down Expand Up @@ -333,7 +336,7 @@ mod tests {
exit_byte_rate: 129000000,
exit_service_rate: 160000000,
},
start_block: 3456,
start_block_opt: None,
scan_intervals: UiScanIntervals {
pending_payable_sec: 150500,
payable_sec: 155000,
Expand Down Expand Up @@ -378,7 +381,7 @@ mod tests {
|Max block count: [Unlimited]\n\
|Neighborhood mode: standard\n\
|Port mapping protocol: PCP\n\
|Start block: 3456\n\
|Start block: [Latest]\n\
|Past neighbors: neighbor 1\n\
| neighbor 2\n\
|Payment thresholds: \n\
Expand Down Expand Up @@ -433,7 +436,7 @@ mod tests {
exit_byte_rate: 20,
exit_service_rate: 30,
},
start_block: 3456,
start_block_opt: Some(1234567890u64),
scan_intervals: UiScanIntervals {
pending_payable_sec: 1000,
payable_sec: 1000,
Expand Down Expand Up @@ -476,7 +479,7 @@ mod tests {
|Max block count: 100,000\n\
|Neighborhood mode: zero-hop\n\
|Port mapping protocol: PCP\n\
|Start block: 3456\n\
|Start block: 1,234,567,890\n\
|Past neighbors: [?]\n\
|Payment thresholds: \n\
| Debt threshold: 2,500 gwei\n\
Expand Down
41 changes: 34 additions & 7 deletions masq/src/commands/set_configuration_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use masq_lib::shared_schema::gas_price_arg;
use masq_lib::shared_schema::min_hops_arg;
use masq_lib::short_writeln;
use masq_lib::utils::ExpectValue;
use std::num::IntErrorKind;

#[derive(Debug, PartialEq, Eq)]
pub struct SetConfigurationCommand {
Expand Down Expand Up @@ -35,9 +36,17 @@ impl SetConfigurationCommand {
}

fn validate_start_block(start_block: String) -> Result<(), String> {
match start_block.parse::<u64>() {
Ok(_) => Ok(()),
_ => Err(start_block),
if "latest".eq_ignore_ascii_case(&start_block) || "none".eq_ignore_ascii_case(&start_block) {
Ok(())
} else {
match start_block.parse::<u64>() {
Ok(_) => Ok(()),
Err(e) if e.kind() == &IntErrorKind::PosOverflow => Err(
format!("Unable to parse '{}' into a starting block number or provide 'none' or 'latest' for the latest block number: digits exceed {}.",
start_block, u64::MAX),
),
Err(e) => Err(format!("Unable to parse '{}' into a starting block number or provide 'none' or 'latest' for the latest block number: {}.", start_block, e))
}
}
}

Expand All @@ -59,7 +68,7 @@ impl Command for SetConfigurationCommand {
const SET_CONFIGURATION_ABOUT: &str =
"Sets Node configuration parameters being enabled for this operation when the Node is running.";
const START_BLOCK_HELP: &str =
"Ordinal number of the Ethereum block where scanning for transactions will start.";
"Ordinal number of the Ethereum block where scanning for transactions will start. Use 'latest' or 'none' for Latest block.";

pub fn set_configurationify<'a>(shared_schema_arg: Arg<'a, 'a>) -> Arg<'a, 'a> {
shared_schema_arg.takes_value(true).min_values(1)
Expand Down Expand Up @@ -103,7 +112,7 @@ mod tests {
);
assert_eq!(
START_BLOCK_HELP,
"Ordinal number of the Ethereum block where scanning for transactions will start."
"Ordinal number of the Ethereum block where scanning for transactions will start. Use 'latest' or 'none' for Latest block."
);
}

Expand All @@ -122,10 +131,28 @@ mod tests {
assert!(result.contains("cannot be used with one or more of the other specified arguments"));
}

#[test]
fn validate_start_block_catches_invalid_values() {
assert_eq!(validate_start_block("abc".to_string()), Err("Unable to parse 'abc' into a starting block number or provide 'none' or 'latest' for the latest block number: invalid digit found in string.".to_string()));
assert_eq!(validate_start_block("918446744073709551615".to_string()), Err("Unable to parse '918446744073709551615' into a starting block number or provide 'none' or 'latest' for the latest block number: digits exceed 18446744073709551615.".to_string()));
assert_eq!(validate_start_block("123,456,789".to_string()), Err("Unable to parse '123,456,789' into a starting block number or provide 'none' or 'latest' for the latest block number: invalid digit found in string.".to_string()));
assert_eq!(validate_start_block("123'456'789".to_string()), Err("Unable to parse '123'456'789' into a starting block number or provide 'none' or 'latest' for the latest block number: invalid digit found in string.".to_string()));
}
#[test]
fn validate_start_block_works() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a bad test because if the function returns an err we want to know if it is an appropriate one, or its message meaningful.

I'd like to see two-sides assertion with Ok(()) or Err("The error message").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this now does what you mean... 2 separate test methods one for Err cases and this one for Ok cases.

assert!(validate_start_block("abc".to_string()).is_err());
assert!(validate_start_block("1566".to_string()).is_ok());
assert_eq!(
validate_start_block("18446744073709551615".to_string()),
Ok(())
);
assert_eq!(validate_start_block("1566".to_string()), Ok(()));
assert_eq!(validate_start_block("none".to_string()), Ok(()));
assert_eq!(validate_start_block("None".to_string()), Ok(()));
assert_eq!(validate_start_block("NONE".to_string()), Ok(()));
assert_eq!(validate_start_block("nOnE".to_string()), Ok(()));
assert_eq!(validate_start_block("latest".to_string()), Ok(()));
assert_eq!(validate_start_block("LATEST".to_string()), Ok(()));
assert_eq!(validate_start_block("LaTeST".to_string()), Ok(()));
assert_eq!(validate_start_block("lATEst".to_string()), Ok(()));
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion masq_lib/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ pub struct UiConfigurationResponse {
#[serde(rename = "portMappingProtocol")]
pub port_mapping_protocol_opt: Option<String>,
#[serde(rename = "startBlock")]
pub start_block: u64,
pub start_block_opt: Option<u64>,
#[serde(rename = "consumingWalletPrivateKeyOpt")]
pub consuming_wallet_private_key_opt: Option<String>,
// This item is calculated from the private key, not stored in the database, so that
Expand Down
4 changes: 2 additions & 2 deletions multinode_integration_tests/docker/blockchain/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved.
FROM trufflesuite/ganache-cli:v6.7.0
FROM trufflesuite/ganache-cli:v6.12.2

ADD ./entrypoint.sh /app/

EXPOSE 18545

ENTRYPOINT /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
7 changes: 6 additions & 1 deletion multinode_integration_tests/docker/blockchain/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#!/bin/sh

node /app/ganache-core.docker.cli.js -p 18545 --networkId 2 --verbose --mnemonic "timber cage wide hawk phone shaft pattern movie army dizzy hen tackle lamp absent write kind term toddler sphere ripple idle dragon curious hold"
node /app/ganache-core.docker.cli.js \
-h 0.0.0.0 \
-p 18545 \
--networkId 2 \
--verbose \
--mnemonic "timber cage wide hawk phone shaft pattern movie army dizzy hen tackle lamp absent write kind term toddler sphere ripple idle dragon curious hold"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not consistent on how we should finish this branch regarding these files in the docker folder.

Do you think it is not reasonable to put the master alike code in here? Especially the comment speaks about things that cannot be found on your branch, instead the GH-711 has it. Deleting the comment is necessary, therefore I'm suggesting to undo the changes in both files:

multinode_integration_tests/docker/blockchain/entrypoint.sh
multinode_integration_tests/docker/blockchain/Dockerfile

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Master does not have -h 0.0.0.0 however BlockchainServer::wait_until_ready(); watches for 10 seconds to find it with output.contains("Listening on 0.0.0.0:18545"). It seems right to be explicit about something the test relies on to succeed. But I can revert it if you prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No probs. I'm no longer concerned about this. You can leave it in if you want to.

16 changes: 7 additions & 9 deletions multinode_integration_tests/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved.

use self::sub_lib::utils::indicates_dead_stream;
use masq_lib::command::{Command, StdStreams};
use masq_lib::constants::{HIGHEST_USABLE_PORT, LOWEST_USABLE_INSECURE_PORT};
use node_lib::sub_lib;
use node_lib::sub_lib::framer::Framer;
use node_lib::sub_lib::node_addr::NodeAddr;
use node_lib::sub_lib::utils::indicates_dead_stream;
use node_lib::test_utils::data_hunk::DataHunk;
use node_lib::test_utils::data_hunk_framer::DataHunkFramer;
use std::borrow::BorrowMut;
Expand All @@ -14,10 +13,9 @@ use std::env;
use std::io;
use std::io::Read;
use std::io::Write;
use std::net::Shutdown;
use std::net::SocketAddr;
use std::net::TcpListener;
use std::net::TcpStream;
use std::net::{Shutdown, SocketAddr};
use std::process;
use std::str::FromStr;
use std::sync::{Arc, Mutex, MutexGuard};
Expand Down Expand Up @@ -223,10 +221,10 @@ impl MockNode {
}

fn usage(stderr: &mut dyn Write) -> u8 {
writeln! (stderr, "Usage: MockNode <IP address>:<port>/<port>/... where <IP address> is the address MockNode is running on and <port> is between {} and {}",
LOWEST_USABLE_INSECURE_PORT,
HIGHEST_USABLE_PORT,
).unwrap ();
writeln!(stderr, "Usage: MockNode <IP address>:<port>/<port>/... where <IP address> is the address MockNode is running on and <port> is between {} and {}",
LOWEST_USABLE_INSECURE_PORT,
HIGHEST_USABLE_PORT,
).unwrap();
1
}

Expand Down Expand Up @@ -369,7 +367,7 @@ mod tests {

assert_eq!(result, 1);
let stderr = holder.stderr;
assert_eq! (stderr.get_string (), String::from ("Usage: MockNode <IP address>:<port>/<port>/... where <IP address> is the address MockNode is running on and <port> is between 1025 and 65535\n\n"));
assert_eq!(stderr.get_string(), String::from("Usage: MockNode <IP address>:<port>/<port>/... where <IP address> is the address MockNode is running on and <port> is between 1025 and 65535\n\n"));
}

#[test]
Expand Down
14 changes: 8 additions & 6 deletions multinode_integration_tests/src/mock_blockchain_client_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,10 @@ impl MockBlockchainClientServer {
let mut requests = requests_arc.lock().unwrap();
requests.push(body);
}
let response = responses.remove(0);
Self::send_body(conn_state, response);
if !responses.is_empty() {
let response = responses.remove(0);
Self::send_body(conn_state, response);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is something we want to have? I don't think so. Let me check if I understand what is going on here: this is a mock server which is supposed to serve requests as if sent to a real blockchain service. And I do think each such a test should also contain the second part, where it awaits a response. The response needs to be set up in the mock before the actual test starts off, if this step is left out it is actually an error of the programmer and therefore it's adequate to halt the test if we happen to find out there's been a request but we can't reach in for a prepared response. That's actually this very moment which you bypassed with the extra if statement.

Correct me if I can't see the improvement beyond your modification. However, unless you do, I'd definitely revert these lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only changed this because responses was empty and causing a panic. I thought it was hiding the real test failure. I can revert it if you prefer.

let _ = notifier_tx.send(()); // receiver doesn't exist if test didn't set it up
}
None => (),
Expand Down Expand Up @@ -437,7 +439,7 @@ mod tests {
.response("Thank you and good night", 40)
.start();
let mut client = connect(port);
client.write (b"POST /biddle HTTP/1.1\r\nContent-Length: 5\r\n\r\nfirstPOST /biddle HTTP/1.1\r\nContent-Length: 6\r\n\r\nsecond").unwrap();
client.write(b"POST /biddle HTTP/1.1\r\nContent-Length: 5\r\n\r\nfirstPOST /biddle HTTP/1.1\r\nContent-Length: 6\r\n\r\nsecond").unwrap();

let (_, body) = receive_response(&mut client);
assert_eq!(
Expand Down Expand Up @@ -567,7 +569,7 @@ mod tests {
assert_eq!(notified.try_recv().is_err(), true);

let requests = subject.requests();
assert_eq! (requests, vec! [
assert_eq!(requests, vec![
"POST /biddle HTTP/1.1\r\nContent-Type: application-json\r\nContent-Length: 82\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\": \"first\", \"params\": [\"biddle\", \"de\", \"bee\"], \"id\": 40}".to_string(),
"POST /biddle HTTP/1.1\r\nContent-Type: application-json\r\nContent-Length: 48\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\": \"second\", \"id\": 42}".to_string(),
"POST /biddle HTTP/1.1\r\nContent-Type: application-json\r\nContent-Length: 47\r\n\r\n{\"jsonrpc\": \"2.0\", \"method\": \"third\", \"id\": 42}".to_string(),
Expand Down Expand Up @@ -600,7 +602,7 @@ mod tests {
r#"{"jsonrpc": "2.0", "result": {"name":"Billy","age":15}, "id": 42}"#
);
let requests = subject.requests();
assert_eq! (requests, vec! [
assert_eq!(requests, vec![
"POST / HTTP/1.1\r\ncontent-type: application/json\r\nuser-agent: web3.rs\r\nhost: 172.18.0.1:32768\r\ncontent-length: 308\r\n\r\n{\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{\"address\":\"0x59882e4a8f5d24643d4dda422922a870f1b3e664\",\"fromBlock\":\"0x3e8\",\"toBlock\":\"latest\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x00000000000000000000000027d9a2ac83b493f88ce9b4532edcf74e95b9788d\"]}],\"id\":0}".to_string()
])
}
Expand Down Expand Up @@ -704,6 +706,6 @@ mod tests {
body.len(),
body
)
.into_bytes()
.into_bytes()
}
}
13 changes: 5 additions & 8 deletions multinode_integration_tests/tests/verify_bill_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ use web3::Web3;

#[test]
fn verify_bill_payment() {
let mut cluster = match MASQNodeCluster::start() {
Ok(cluster) => cluster,
Err(e) => panic!("{}", e),
};
let mut cluster = MASQNodeCluster::start().unwrap();
let blockchain_server = BlockchainServer {
name: "ganache-cli",
};
Expand All @@ -64,7 +61,7 @@ fn verify_bill_payment() {
assert_balances(
&contract_owner_wallet,
&blockchain_interface,
"99998043204000000000",
"99998381140000000000",
"472000000000000000000000000",
);
let payment_thresholds = PaymentThresholds {
Expand Down Expand Up @@ -189,7 +186,7 @@ fn verify_bill_payment() {
assert_balances(
&contract_owner_wallet,
&blockchain_interface,
"99998043204000000000",
"99998381140000000000",
"472000000000000000000000000",
);

Expand Down Expand Up @@ -235,7 +232,7 @@ fn verify_bill_payment() {
assert_balances(
&contract_owner_wallet,
&blockchain_interface,
"99997886466000000000",
"99998223682000000000",
"471999999700000000000000000",
);

Expand Down Expand Up @@ -330,7 +327,7 @@ fn assert_balances(
assert_eq!(
format!("{}", eth_balance),
String::from(expected_eth_balance),
"Actual EthBalance {} doesn't much with expected {}",
"Actual EthBalance {} doesn't match with expected {}",
eth_balance,
expected_eth_balance
);
Expand Down
13 changes: 11 additions & 2 deletions node/src/accountant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ mod tests {
use crate::blockchain::test_utils::{make_tx_hash, BlockchainInterfaceMock};
use crate::database::rusqlite_wrappers::TransactionSafeWrapper;
use crate::database::test_utils::transaction_wrapper_mock::TransactionInnerWrapperMockBuilder;
use crate::db_config::config_dao::ConfigDaoRecord;
use crate::db_config::mocks::ConfigDaoMock;
use crate::match_every_type_id;
use crate::sub_lib::accountant::{
Expand Down Expand Up @@ -1373,7 +1374,11 @@ mod tests {
config.suppress_initial_scans = true;
let subject = AccountantBuilder::default()
.bootstrapper_config(config)
.config_dao(ConfigDaoMock::new().set_result(Ok(())))
.config_dao(
ConfigDaoMock::new()
.get_result(Ok(ConfigDaoRecord::new("start_block", None, false)))
.set_result(Ok(())),
)
.build();
let (ui_gateway, _, ui_gateway_recording_arc) = make_recorder();
let subject_addr = subject.start();
Expand Down Expand Up @@ -1991,6 +1996,7 @@ mod tests {
) {
let more_money_received_params_arc = Arc::new(Mutex::new(vec![]));
let commit_params_arc = Arc::new(Mutex::new(vec![]));
let get_params_arc = Arc::new(Mutex::new(vec![]));
let set_by_guest_transaction_params_arc = Arc::new(Mutex::new(vec![]));
let now = SystemTime::now();
let earning_wallet = make_wallet("earner3000");
Expand All @@ -2014,6 +2020,8 @@ mod tests {
.more_money_received_params(&more_money_received_params_arc)
.more_money_received_result(wrapped_transaction);
let config_dao = ConfigDaoMock::new()
.get_params(&get_params_arc)
.get_result(Ok(ConfigDaoRecord::new("start_block", None, false)))
.set_by_guest_transaction_params(&set_by_guest_transaction_params_arc)
.set_by_guest_transaction_result(Ok(()));
let accountant = AccountantBuilder::default()
Expand All @@ -2028,7 +2036,7 @@ mod tests {
.try_send(ReceivedPayments {
timestamp: now,
payments: vec![expected_receivable_1.clone(), expected_receivable_2.clone()],
new_start_block: 123456789,
new_start_block: 123456789u64,
response_skeleton_opt: None,
})
.expect("unexpected actix error");
Expand Down Expand Up @@ -4774,6 +4782,7 @@ mod tests {
let factory = Accountant::dao_factory(data_dir);
factory.make();
};

assert_on_initialization_with_panic_on_migration(&data_dir, &act);
}
}
Expand Down
Loading