-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GH-600: Add get_block_number #193
Conversation
masqrauder
commented
Nov 28, 2022
- Introduce the ability to get the current block number of a chain.
- Utilize batch transport to request block number and transaction logs within the same blockchain service provider API batch request.
- Incrementally scan the blockchain for payments and use the upper block number bound as required.
- Handle block number range errors reported by blockchain service providers to allow recovery and catch up to the current block if the node falls behind.
@@ -254,12 +276,22 @@ where | |||
) | |||
.build(); | |||
|
|||
let log_request = self.web3.eth().logs(filter); | |||
let end_block_number = match Option::from(end_block) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're wrapping the value so that you take the covering away just a moment later. Instead, you can ignore the Option and just write:
let end_block_number = match end_block {
BlockNumber::Number(eb) => eb.as_u64(),
_ => start_block + 1,
};
Also, related to the suggestion at args, this name should probably change a bit too, so that it better fits to the choice for the name of the argument up there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What name do you recommend instead of end_block_number
? It's really a fallback value that is used in the event there's an error in retrieving the latest block number from the chain. This value may also be changed after GH-585 where the blockchain service might provide a maximum block count delta from the start block as a limitation we have to use on subsequent calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually fallback_end_block_number
or somehow shorter looks good to me. (I know you've got better sense for the language, so I'm not suggesting nothing but that the word fallback
would be nice to have in there). What do you think? It might stop making people wonder about what that is.
@@ -232,6 +253,7 @@ where | |||
fn retrieve_transactions( | |||
&self, | |||
start_block: u64, | |||
end_block: BlockNumber, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do recommend to use a clearer name here, because variables like this one are mentioned a few times through this function. It's not so easy to read and understand.
My suggestions: minimal_end_block
, null_end_block
, smallest_possible_end_block
...I'm quite sure you will be better at finding an appropriate name.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could potentially wrap start_block
and end_block
in a new block range datatype if you think it warrants it. The web3 interface uses the BlockNumber
enum for from_block
and to_block.
For our use case, if we were to use BlockNumber
for start_block
some of the enum values don't make sense like BlockNumber::Pending
We could interpret BlockNumber::Earliest
as the MASQ smart contract block number, but that would not fit the true web3 meaning. But then again for the most part we want to use BlockNumber::Latest
for someone starting node for the first time with a new wallet address.
future::result::<RetrievedBlockchainTransactions, BlockchainError>(match logs { | ||
match self.web3_batch.transport().submit_batch().wait() { | ||
Ok(_) => { | ||
let block_number = match block_request.wait() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a name like: possibly_updated_block_number
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this working value name could be better as response_block_number
because it's in response to our block number request call. This value may be impacted by GH-585 error handling for error responses providing a max block range value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, in general, I'm all for naming variables with more meaningful names, if they are somehow specific or different from other ones. So I think it'd be an improvement.
Ok(latest_block_number) => assert_eq!(latest_block_number, U64::from(31_682_662u64)), | ||
Err(e) => assert_eq!( | ||
e, | ||
BlockchainError::QueryFailed("unexpected failure".to_string()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a strange way of handling an unfavorable result.
Instead of an assertion which tends to be used for an expected behavior, it's more appropriate to use panic!(), printing the error, whatever it is, with a simple msg.
I' making the point because I'm assuming this test focuses on a success on this method call...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I should think more in terms of production vs test code.
let actual_arguments: Vec<String> = actual_arguments | ||
.into_iter() | ||
.map(|arg| serde_json::to_string(&arg).unwrap()) | ||
.collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the params of the prepare method are hard-coded, that is an empty vector, and so you will always get the same result for such a param assertion I'd welcome a simpler way of going through it.
You can skip the step above, trying to iterate over an empty vector, leaving:
let (method_name, actual_arguments) = prepare_params.remove(0);
assert_eq!(method_name, "eth_blockNumber".to_string());
let expected_arguments: Vec<Value> = vec![];
assert_eq!(actual_arguments, expected_arguments);
The same should be preferably done with all the following tests too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. The point of this part of the test was to confirm that there are no arguments passed to the method. I was keeping the tests consistent so that you don't have to mentally switch gears back and forth. I guess this had the opposite effect. If there's a better way to ensure the test breaks appropriately if the arguments change, then I'd like to follow that. I was too focused on trying to get data type held by the vector to be consistent I didn't think of what you have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know, for now the assertion testing an empty vector is good enough. If it changes it will definitely breaks. But again, that parameter is so-far constant. One could point out it could change with a different version of the library.
For clarity, I didn't complain about the fact you want to assert on this parameter I just didn't see a point in converting the potential values to a different, maybe better assertable data types. That step just prolongs the test even though it makes no difference. The vector is empty at any case.
let end_block = match self.blockchain_interface.get_block_number() { | ||
Ok(eb) => BlockNumber::Number(eb), | ||
Err(_) => BlockNumber::Latest, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm reluctant to believe that both of those branches of the match are adequately tested. I miss one test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resume at blockchain_interface:287 green
@@ -232,6 +253,7 @@ where | |||
fn retrieve_transactions( | |||
&self, | |||
start_block: u64, | |||
end_block: BlockNumber, |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -275,40 +307,51 @@ where | |||
let transactions: Vec<BlockchainTransaction> = logs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hunk of code seems like something that could live in an outboard method and make the caller clearer.
}); | ||
// transactions, in which case use end_block, unless get_latest_block() | ||
// was not successful. | ||
let transaction_max_block_number = if transactions.is_empty() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hunk of code seems like something that could live in an outboard method and make the caller clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Continue at blockchain_interface.rs: blockchain_interface_non_clandestine_can_transfer_tokens
.filter_map(|log: &Log| match log.block_number { | ||
None => None, | ||
Some(block_number) => { | ||
to_gwei(U256::from(log.data.0.as_slice())).map(|gwei_amount| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this idea is silly but what if you put the value log.data.0
on a different line and give it a name through using a variable. Readability of the code might get better. I'll let you decide if it's worth it. But you know, only the person who will go to the source code of the library will really know what this is exactly.
BlockchainTransaction { | ||
block_number: block_number.as_u64(), | ||
from: Wallet::from(log.topics[1]), | ||
gwei_amount, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One important thing here, by the time of this writing we've got already "in-wei counting" system implemented. That means that the other Nodes will probably pay you something different than just clear gwei values. These numbers moved between Nodes are going to be much more accurate. So you don't want to lose the accuracy here by conversion to gwei. You'll have to change the field's name and the data type to u128, plus get rid of the conversion.
It might be the case that it will be automatically taken care of by doing the merge (I might have adjusted this code already...well, given your method is now concise and placed alone...the merge might not affect this code...but its mostly the same so maybe yes.). Please check it out anyway.
@@ -640,13 +716,13 @@ mod tests { | |||
std::env::set_var("SIMPLESERVER_THREADS", "1"); | |||
let (tx, rx) = unbounded(); | |||
let _ = thread::spawn(move || { | |||
let bodies_arc = Arc::new(Mutex::new(bodies)); | |||
let bodies_arc: Arc<Mutex<Vec<Vec<u8>>>> = Arc::new(Mutex::new(bodies)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type definition shouldn't be necessary but if you want it to stay, okay.
Server::new(move |req, mut rsp| { | ||
if req.headers().get("X-Quit").is_some() { | ||
panic!("Server stop requested"); | ||
} | ||
tx.send(req).unwrap(); | ||
let body = bodies_arc.lock().unwrap().remove(0); | ||
let body: Vec<u8> = bodies_arc.lock().unwrap().remove(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly...
We usually don't do this if the compiler knows the truth and you as a human can read it out of the combination of the function signature and the code in the body. I'm saying that just for your better knowledge. I don't find it serious though and won't request a change.
format!("\"0x000000000000000000000000{}\"", &to[2..]), | ||
bodies[0]["params"][0]["topics"][2].to_string(), | ||
vec![format!("[{{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[]}},{{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{{\"address\":\"0x384dec25e03f94931767ce4c3556168468ba24c3\",\"fromBlock\":\"0x2a\",\"toBlock\":\"0x400\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x000000000000000000000000{}\"]}}]}}]", &to[2..])], | ||
bodies //bodies[0]["params"][0]["topics"][1].to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a policy of putting the value being asserted on the left side of the assert_eq!()
macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you're saying actual
then expected
? I think these escaped the initial policy switch. I think this code was originally written with expected
then actual
order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Yeah, sometimes we still come across some old tests where it's reversed.
Confirming that this is the preferred style: assert_eq!(actual, expected)
format!("\"0x000000000000000000000000{}\"", &to[2..]), | ||
bodies[0]["params"][0]["topics"][2].to_string(), | ||
vec![format!("[{{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[]}},{{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{{\"address\":\"0x384dec25e03f94931767ce4c3556168468ba24c3\",\"fromBlock\":\"0x2a\",\"toBlock\":\"0x400\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x000000000000000000000000{}\"]}}]}}]", &to[2..])], | ||
bodies //bodies[0]["params"][0]["topics"][1].to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this whole structure:
vec![format!("[{{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[]}},{{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{{\"address\":\"0x384dec25e03f94931767ce4c3556168468ba24c3\",\"fromBlock\":\"0x2a\",\"toBlock\":\"0x400\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x000000000000000000000000{}\"]}}]}}]", &to[2..])]
,
which you use in the assertion as the template is equal to the variable bodies
.
That's why the comment //bodies[0]["params"][0]["topics"][1].to_string(),
is pointless what more, it's confusing. I'm asking you to remove it.
format!("\"0x000000000000000000000000{}\"", &to[2..]), | ||
bodies[0]["params"][0]["topics"][2].to_string(), | ||
vec![format!("[{{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[]}},{{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{{\"address\":\"0x384dec25e03f94931767ce4c3556168468ba24c3\",\"fromBlock\":\"0x2a\",\"toBlock\":\"0x400\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x000000000000000000000000{}\"]}}]}}]", &to[2..])], | ||
bodies, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also reverse the asserted value with the asserting one.
); | ||
assert_eq!( | ||
result, | ||
RetrievedBlockchainTransactions { | ||
new_start_block: 0x4be663 + 1, | ||
new_start_block: 0x4be663, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this block going to be included in the next scan? Because if yes then it is the same as the block of the last transaction we found and so we would pick that transaction again. Please verify.
let (event_loop_handle, transport) = Http::with_max_parallel( | ||
&format!("http://{}:{}", &Ipv4Addr::LOCALHOST, port), | ||
&format!("http://{}:{}", &Ipv4Addr::LOCALHOST.to_string(), port), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.to_string()
inside the format!() macro is redundant. Format will do it itself.
assert_eq!( | ||
actual_arguments, | ||
vec![String::from( | ||
r#""0xf8a901851bf08eb00082dbe894384dec25e03f94931767ce4c3556168468ba24c380b844a9059cbb00000000000000000000000000000000000000000000000000626c61683132330000000000000000000000000000000000000000000000000000082f79cd900029a0d4ecb2865f6a0370689be2e956cc272f7718cb360160f5a51756264ba1cc23fca005a3920e27680135e032bb23f4026a2e91c680866047cf9bbadee23ab8ab5ca2""# |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what the seemingly blank line (or really white spaces?) at the beginning of the line 1301 means. I'd feel better if you had a look at it to check out for some strange formatting and to confirm it's false alarm 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know. It's just the formatter adding the indentation.
assert!(prepare_params.is_empty()); | ||
let actual_arguments: Vec<String> = actual_arguments | ||
.into_iter() | ||
.map(|arg| serde_json::to_string(&arg).unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do this as often that it would have some positive effect if you created a helper function (used only this test module) which would take the a parameter with the type of actual_arguments
and it would return a Vec<String>
.
It will take care of duplication and make the tests slightly shorter.
|
||
#[test] | ||
fn non_clandestine_can_fetch_latest_block_number_successfully() { | ||
let prepare_params_arc: Arc<Mutex<Vec<(String, Vec<Value>)>>> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The explicit type should not be necessary to understand the test and the compiler will not complain too.
); | ||
|
||
match subject.get_block_number() { | ||
Ok(latest_block_number) => assert_eq!(latest_block_number, U64::from(31_682_662u64)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please interpret this expected number also as a hexadecimal number? The understanding is gonna be easier thanks to the fast comparison of those two values, even though as different data types.
U64::from(0x1e37066u64)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Also, the test would be easier to read if you untangled the Assert from the Act.
node/src/blockchain/test_utils.rs
Outdated
send_batch_params: Arc<Mutex<Vec<Vec<(RequestId, rpc::Call)>>>>, | ||
send_batch_results: RefCell<Vec<Vec<Result<rpc::Value, web3::Error>>>>, | ||
//to check if we hold a true descendant of a certain initial instance | ||
reference_counter_opt: Option<Arc<()>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably don't need the two last lines. I implemented them but your version of the codebase doesn't need it.
It would stay idle for a while and it's better not to add it in now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resume at blockchain_interface:822 green.
Err(e) => { | ||
warning!( | ||
self.logger, | ||
"Using 'latest' block number instead of a literal number. {:?}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it going to be clear from context what the latest block number is being used for, and what the consequences of that will be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it should be informational instead of a warning? It's not meant to sound bad or dangerous; only that we couldn't fetch the current block number and so now we're just going to query using BlockNumber::Latest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it sounds like something that ought to be an info!()
instead of a warning!()
.
assert_eq!( | ||
format!("\"0x000000000000000000000000{}\"", &to[2..]), | ||
bodies[0]["params"][0]["topics"][2].to_string(), | ||
bodies, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any danger that this assert will be disrupted by JSON formatting? Say, if somehow we get spaces after the commas, or newlines, or indentation, or whatever? If so, it might be better to compare these two as parsed objects rather than JSON strings.
From Bert: you could eliminate a lot of the backslashes if you used r#"
quotes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this breaks because of json formatting I suspect that means the block chain service has changed and we'd want the broken test to warn us of that. The raw jsonrpc response is how we see the data and is very compact without extra spaces and new lines. Do you have another suggestion to do instead?
I saw Bert's comment regarding the format!()
I could remove the format to eliminate the escaping but this means the &to[2..]
address would have to be hardcoded in an additional place. Do you prefer it hardcoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't give the life for being right on this but I think it would allow you to use format!()
also with r#"...text..."...text..."#
literals that contain double quotes and it even can have a placeholder in it like {}
or {:?}
and it should still work as long as you supply that many arguments as how many placeholders you put in there. You can try but maybe not worth it.
} | ||
|
||
#[test] | ||
fn blockchain_interface_non_clandestine_retrieve_transactions_returns_an_error_if_a_response_with_data_that_is_too_long_is_returned( | ||
fn blockchain_interface_non_clandestine_retrieve_transactions_ignores_transaction_logs_that_have_no_block_number( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that transaction logs without block numbers are probably not a pressing real-world problem, and that you have to handle them only because we're not allowed to crash because of something that comes in from outside; but just in case it does happen, would it be worth writing an error log?
); | ||
|
||
match subject.get_block_number() { | ||
Ok(latest_block_number) => assert_eq!(latest_block_number, U64::from(31_682_662u64)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Also, the test would be easier to read if you untangled the Assert from the Act.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed a few things, but nothing that would cause real trouble, so I'll approve. It'd be nice if you'd take a look through the comments anyway, though.
if logs | ||
.iter() | ||
.any(|log| log.topics.len() < 2 || log.data.0.len() > 32) | ||
{ | ||
warning!( | ||
logger, | ||
"Invalid response from blockchain server: {:?}", | ||
logs | ||
logs.clone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bert wonders: does the macro really take ownership here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't. I removed the .clone()
transactions: vec![], | ||
}), | ||
Err(e) => { | ||
error!(self.logger, "Retrieving transactions: {}", e.to_string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the .to_string()
is unnecessary here. Doesn't the {}
placeholder automatically call the Display
implementation, which is what .to_string()
does?
(Bert says, "Hell, yes!")
.collect(); | ||
assert_eq!( | ||
bodies, | ||
vec![format!("[{{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[]}},{{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{{\"address\":\"0x384dec25e03f94931767ce4c3556168468ba24c3\",\"fromBlock\":\"0x2a\",\"toBlock\":\"0x400\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",null,\"0x000000000000000000000000{}\"]}}]}}]", &to[2..])], | ||
bodies[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked the strength of the assertion that bodies
was equal to vec[
-just one thing-]
, because it included the requirement that there could only be one element in the vector.
Also, you could DRY that back up, if you wanted, by doing something like
let expected_body_prefix =
-complicated #r
string ending in zeros-;
let expected_body = format!("{}{}", expected_body_prefix, &to[2..]);
assert_eq!(bodies, vec[expected_body]);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used your recommended changes but could not do so without introducing an expected_body_suffix
for the closing JSON syntax. It would be nice if format!()
could work with raw Strings.
@@ -1011,6 +1010,10 @@ mod tests { | |||
transactions: vec![] | |||
}) | |||
); | |||
let test_log_handler = TestLogHandler::new(); | |||
test_log_handler.assert_logs_contain_in_order(vec![ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks as though it would work fine, but why .assert_logs_contain_in_order
instead of .exists_log_containing
?
@@ -2223,19 +2236,21 @@ mod tests { | |||
TEST_DEFAULT_CHAIN, | |||
); | |||
|
|||
match subject.get_block_number() { | |||
let expected_error = match subject.get_block_number() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can do subject.get_block_number().unwrap_err()
here and ditch the match
, if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see a change making the assertion simpler and obvious at what is important in the error message. Also without if statements involved that aren't becoming to assertions in general.
Hopefully you will agree 🙏
.retrieve_transactions(start_block, &msg.recipient); | ||
let retrieved_transactions = | ||
self.blockchain_interface | ||
.retrieve_transactions(start_block, end_block, &msg.recipient); | ||
match retrieved_transactions { | ||
Ok(transactions) => { | ||
if let Err(e) = self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put a debug log here announcing the newly picked start block before you write it into the db. It's going to make debugging a lot easier for the future.
match self.web3_batch.transport().submit_batch().wait() { | ||
Ok(_) => { | ||
let response_block_number = match block_request.wait() { | ||
Ok(block_nbr) => block_nbr.as_u64(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also here, this would be such good information for a debugging person. Please add the debug log saying what current head block was reported from the blockchain.
8a01f3a
to
2c93c9b
Compare
027efbc
to
849d8be
Compare
0a6f901
to
673763c
Compare
GH-600: Add get_block_number GH-600: Address PR feedback GH-585: Experiment with adapting test for platform specific error codes GH-585: Provide Windows platform specific error code and message GH-600: Rebase master into branch
* Starts Accountant * Adds Receivables scan timeout (may become a configuration parameter in another card) * Stores `max_block_count` in the config table when processing error messages providing a limit * Adds Max Block Count to configuration response * Increments CURRENT_SCHEMA_VERSION * Adds schema migration for `max_block_count` * Improves blockchain scan error handling and logging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding approval for PR merge