Skip to content
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

Sync with multiple peers #37

Merged
merged 7 commits into from
Oct 26, 2016
Merged

Sync with multiple peers #37

merged 7 commits into from
Oct 26, 2016

Conversation

svyatonik
Copy link
Contributor

Started work on multiple peers support in sync + added several basic sync tests.
Synchronization strategy is described in sync/src/synchronization.rs, however there are a lot TODOs.

Current functionality:
able to read blocks from single (potentially - many, however, not tested this scenario) peer && store in in-memory-storage (without any verification, except for header.parent_hash = hash(parent))
tested with bitcoind

Next steps:

  1. integrate with db && verification packages to make it work together
  2. add another tests
  3. work on TODOs
  4. headers-first sync
  5. processing other sync messages

@svyatonik
Copy link
Contributor Author

@NikVolf currently sync/src/local_chain.rs is used as in-memory storage && there is some code in sync/src/synchronization.rs which links (well, it should :) ) together storage && verification queue.
So I think I'll change it this way:

  1. db::Store as storage instead of LocalChain
  2. LocalChain becomes facet for db::Store + verification::Queue (maybe other parts later)

self.orphan_blocks.insert(block.block_header.previous_header_hash.clone(), block.clone());
return;
}
assert!(self.blocks_map.contains_key(&block.block_header.previous_header_hash));
Copy link
Contributor

Choose a reason for hiding this comment

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

is it because block is already verified?

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 - currently LocalChain is what is database is supposed to be (without fork support) - only verified in-order blocks are here.


// process unknown blocks
let unknown_blocks: Vec<_> = message.inventory.iter()
.filter(|item| InventoryType::from_u32(item.inv_type) == Some(InventoryType::MessageBlock))
Copy link
Contributor

Choose a reason for hiding this comment

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

not an issue. Maybe item.inv_type could be InventoryType instead of u32?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would be great. I doubt anybody will ever need to have access to underlying values of enums + check is moved to deserialization step (which is good, because we can drop connections without even interacting with sync module)

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'll add TODO for this

///! 2) no forks support
///!
///! When new peer is connected:
///! 1) send `getdata` message with full block locator hashes
Copy link
Contributor

Choose a reason for hiding this comment

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

few questions :)
in the docs getdata message description says

getdata is used in response to inv, to retrieve the content of a specific object, and is usually sent after receiving an inv packet, after filtering known elements

how does it correspond with the docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mistake here - sorry :) Actually inv message is sent. Will fix this

}
SynchronizationTask::RequestInventory(peer_index) => {
let getblocks = types::GetBlocks {
version: 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it ok to send 0 instead of real protocol version? What if some implementations expect real protocol version here? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, thank you :) I think I should look into it, because for now it is not clear to me - which version should I pass here. Is it negotiated version (during handshake)? Or is it version of the protocol, this particular message was defined in? For example: in PV 0...1000 message1 had 5 fields and since that it have 10 fields.
In protocol documentation it is described as "the protocol version". But if we have negotiated version earlier, then why should I pass it everytime with the message? And if it is this particular message version, then 0 is OK because structure of getblocks message (and other messages I use here) hasn't changed since bitcoin beginning.
I'll add TODO here.

Copy link
Contributor

Choose a reason for hiding this comment

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

@debris
Copy link
Contributor

debris commented Oct 26, 2016

lgtm

@debris debris merged commit 4804ac5 into master Oct 26, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants