-
Notifications
You must be signed in to change notification settings - Fork 20.5k
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
core, eth: split eth package, implement snap protocol #21482
Conversation
596f17b
to
c610a46
Compare
49151a8
to
1e2609f
Compare
1e2609f
to
cdb49b1
Compare
Database ethdb.Database // Database for direct sync insertions | ||
Chain *core.BlockChain // Blockchain to serve data from | ||
TxPool txPool // Transaction pool to propagate from | ||
Network uint64 // Network identifier to adfvertise |
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.
Network uint64 // Network identifier to adfvertise | |
Network uint64 // Network identifier to advertise |
|
||
func (pm *ProtocolManager) runPeer(p *peer) error { | ||
if !pm.chainSync.handlePeerEvent(p) { | ||
// runEthPeer |
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.
missing documentation
// Read the next message from the remote peer, and ensure it's fully consumed | ||
msg, err := p.rw.ReadMsg() | ||
if err != nil { | ||
// runSnapPeer |
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.
missing documentation here too
if eth != nil { | ||
eth.Peer.Disconnect(p2p.DiscUselessPeer) | ||
} | ||
if snap != nil { |
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 a reason for doing the additional check for snap != nil
down here too?
can you disconnect useless peer after unregistering the peer after L346?
446ca23
to
fc1ebdb
Compare
eth/downloader/downloader.go
Outdated
func (d *Downloader) RegisterPeer(id string, version int, peer Peer) error { | ||
logger := log.New("peer", id) | ||
func (d *Downloader) RegisterPeer(id string, version uint, peer Peer) error { | ||
logger := log.New("peer", id[:16]) |
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.
geth copydb
causes this to panic:
logger := log.New("peer", id[:16])
logger.Trace("Registering sync peer")
if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil ```
dcdc3de
to
0bf5df5
Compare
0bf5df5
to
6451a84
Compare
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.
A few comments
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.
Some potential DoS vectors (?)
trie/proof.go
Outdated
for i := 0; i < len(keys)-1; i++ { | ||
if bytes.Compare(keys[i], keys[i+1]) >= 0 { | ||
return errors.New("range is not monotonically increasing"), false | ||
return nil, nil, false, errors.New("range is not monotonically increasing") | ||
} | ||
} |
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.
Would't it make sense to have this check include firstKey
and lastKey
aswell? Something like this:
var pKey = firstKey
for i := 0; i < len(keys)-1; i++ {
if bytes.Compare(pKey, keys[i]) >= 0 {
return nil, nil, false, errors.New("range is not monotonically increasing")
}
pKey = keys[i]
}
if bytes.Compare(pKey, keys[len(keys)-1]) >= 0 {
return nil, nil, false, errors.New("range is not monotonically increasing")
}
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.
Or rather
// Ensure the received batch is monotonic increasing.
if firstKey != nil && len(keys) > 0 {
if bytes.Compare(firstKey, keys[0]) > 0 {
return nil, nil, false, errors.New("range is not monotonically increasing [0]")
}
}
for i := 0; i < len(keys)-1; i++ {
if bytes.Compare(keys[i], keys[i+1]) >= 0 {
return nil, nil, false, errors.New("range is not monotonically increasing [1]")
}
}
if lastKey != nil && len(keys) > 0 {
if bytes.Compare(keys[len(keys)-1], lastKey) > 0 {
return nil, nil, false, errors.New("range is not monotonically increasing [2]")
}
}
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.
For the snap implementation, this doesn't matter, since AFAICT the snap callers always only send in the origin
and the last key as firstKey
and lastKey
.
defer func() { | ||
// Cancel active request timers on exit. Also set peers to idle so they're | ||
// available for the next sync. | ||
for _, req := range active { | ||
req.timer.Stop() | ||
req.peer.SetNodeDataIdle(int(req.nItems), time.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.
Hm, odd that we don't have this on master, if it's something we should have ?
Random memo: We can eventually make the protocol types (messages, numbers) public so they can be used by external testre frameworks without redefining them localy. |
On a branch of mine, |
On that same this-pr-on-master, I put bench03 and 04 to do snap-sync instead ( Note though, they're not running with karalabe#42, so they might stall eventually. |
It seems that
|
Hm, it's this one: https://github.com/ethereum/discv4-dns-lists/blob/master/snap.mainnet.ethdisco.net/nodes.json#L18 . So apparently there are 6 |
Later in the evening, at about 20:30, |
} else { | ||
cfg.TrieCleanCache += cfg.SnapshotCache | ||
cfg.SnapshotCache = 0 // Disabled | ||
} |
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 !ctx.GlobalIsSet(SnapshotFlag.Name) && cfg.SyncMode != downloader.SnapSync {
cfg.TrieCleanCache += cfg.SnapshotCache
cfg.SnapshotCache = 0 // Disabled
}
// If snap-sync is requested, this flag is also required | ||
if cfg.SyncMode == downloader.SnapSync { | ||
log.Info("Snap sync requested, enabling --snapshot") | ||
ctx.Set(SnapshotFlag.Name, "true") |
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 line is a noop.
@@ -460,7 +460,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I | |||
} | |||
}() | |||
if p.version < 64 { | |||
return errTooOld | |||
return fmt.Errorf("%w, peer version: %d", errTooOld, p.version) |
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.
%w:
:P
@karalabe Would you explain a bit more details why we need the heal phase for the snap protocol? Thank you so much! |
@hadv Geth maintains 1 persistent snapshot layer on disk and 128 diff layers in memory. This means, that if you start syncing the head snapshot, after 128 block (~30 minutes), that snapshot will not be available any more in the network. Geth then switches to continuing sync on a new snapshot, but that won't match the old one. We do this until we sync everything, but by that time, we have pieces of many different snapshots (count depending on how fast you can sync up). The heal phase just "glues" these snapshot layers together, plus integrates any changes that have occurred since you've downloaded a particular snapshot segment. |
This PR is a rebase of #20800. Since the code changed quite a lot and I needed to do an ugly rebase, I wanted to have the old code exist somewhere to compare if something does't behave correctly.
WIP