Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Nov 18, 2024. It is now read-only.

[WIP] send block#67

Draft
gurghet wants to merge 12 commits intofeeless:mainfrom
gurghet:wip-send-block
Draft

[WIP] send block#67
gurghet wants to merge 12 commits intofeeless:mainfrom
gurghet:wip-send-block

Conversation

@gurghet
Copy link
Contributor

@gurghet gurghet commented Apr 4, 2021

This will address #59 (comment) but actually for the state block since no send blocks can be found alive. (I will also create an issue for that). The checks however are almost the same.

  • logging receipt (mostly for debug purposes)
  • epoch
  • deduplication
  • previous not found
  • previous not compatible
  • frontier present
  • signature valid
  • work sufficient
  • non negative balance

@gurghet gurghet changed the title Wip send block [WIP] send block Apr 4, 2021
Copy link
Collaborator

@gak gak left a comment

Choose a reason for hiding this comment

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

Good stuff so far!


impl Display for Block {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let work_render = if self.work.is_none() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I prefer this for various reasons, especially because there is no need to do an unwrap (even though it's safe, it could not be in the future if edited incorrectly by someone else):

match &self.work {
    Some(work_render) => work_render.to_string(),
    None => "No work".to_string(),
}

} else {
self.signature.as_ref().unwrap().to_string()
};
write!(f, "Block(Account: {}, Previous: {:?}, Balance: {}, Link: {:?}, Work: {}, Signature: {})",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are you running rustfmt? The IntelliJ plugin has settings that can automatically do rustfmt on save. Make sure you set Use rustfmt instead of built-in formatter too.

image

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 did, it probably reverted for some reason

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw, can we enforce this at CI level?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I will do this today :)

BlockHolder::State(state_block) => {
let mut block = Block::from_state_block(&state_block);
let block_hash: &BlockHash = {
block.calc_hash().unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use context()? or with_context()? instead of unwrap so we can handle problems gracefully instead of panicking.

Copy link
Contributor Author

@gurghet gurghet Apr 4, 2021

Choose a reason for hiding this comment

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

Ah right. Btw I'm starting to be more convinced about requiring a hash to create a valid block. The only reason we put it separately is in case it fails, but I'm quite sure that a hash can't fail per se, so if it fails it's a programming defect (unrecoverable error in Rust lingo). In other words, I don't think it makes sense to keep a block around incapable of having a hash.

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK, if you're convinced go ahead!

};
// dbg!(state_block);

// # deduplication
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the # for? 😅

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 means important comment here! Just kidding, I'm going to delete all the comments before committing anyway.


// # signature validation
let invalid_signature = || {
let valid_signature = block.verify_self_signature()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can just do block.verify_signature().is_ok() or .is_err() to get a bool.

Does it need to be a closure?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes because otherwise it will be computed even if not necessary. On the other hand we could just use a different pattern. Remember the if else question in the discord? It was about this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess if it turns into the is_ok() variant, it won't be computed if the first if branch is true.

As in } else if block.verify_self_signature().is_err() {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, and for this example is fine because it can be reasonably turned into a one liner. I'm concerned whether it can be done for all. For example if the other checks are more elaborate they might not fit inline. I'll write a few more and see what's the result.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess in that case the whole if statement could go into a function with early exits, similar to your initial example in chat?

Copy link
Contributor Author

@gurghet gurghet Apr 5, 2021

Choose a reason for hiding this comment

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

I don't think my first example would help. For reference it was:

if cond1 {
  do_bla();
  return Ok()
}
if cond2 {
  do_bla2();
  return Ok()
}
...

Now, if cond1 needs to lock the state and search the database for example, is not going to look pretty. This is why closures are a good way to group and name the checks on top of the ifs, whatever pattern we chose. I'm trying to think of other options but basically what we have to implement here is a very extensive flow diagram. Any other idea? Btw, in the ref implementation it's a big pile of nested ifs. It's quite legible to be honest but I think we can do much better. (ref code)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well let's just leave it at what you think is best. If we can find a nicer solution later, it shouldn't be a big deal to change.

block.calc_hash().unwrap();
let block_holder = BlockHolder::State(state_block);
controller.handle_publish(&test_header, Publish { block_holder }).await.unwrap();
assert!(controller.state.lock().await.get_block_by_hash(block.hash().unwrap()).await.unwrap().is_none())
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

#[derive(Debug)]
pub struct Publish(pub(crate) BlockHolder);
pub struct Publish {
pub(crate) block_holder: BlockHolder
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

publish.0 feels a bit weird, does this make it weirder? It helped me keep in mind I was working with a BlockHolder anyways.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think .0 is ok, although I do think it's a bit ugly. OK let's keep your change and see how it goes.

@gurghet
Copy link
Contributor Author

gurghet commented Apr 4, 2021

Thanks for the review!

let block = block; // give up mutability for safety

if Controller::block_existed(self, block_hash).await? {
tracing::info!("Block {} already exists!", block_hash);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please just use the info! macro via a use tracing::info

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants