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

Adding ChainSync to spec (WIP) #568

Merged
merged 9 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
513 changes: 473 additions & 40 deletions src/systems/filecoin_blockchain/chainsync/_index.md

Large diffs are not rendered by default.

107 changes: 0 additions & 107 deletions src/systems/filecoin_blockchain/chainsync/block_syncer.go

This file was deleted.

82 changes: 0 additions & 82 deletions src/systems/filecoin_blockchain/chainsync/block_syncer.id

This file was deleted.

1 change: 1 addition & 0 deletions src/systems/filecoin_blockchain/chainsync/chainsync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package chainsync
101 changes: 101 additions & 0 deletions src/systems/filecoin_blockchain/chainsync/chainsync.id
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import ipld "github.com/filecoin-project/specs/libraries/ipld"
import block "github.com/filecoin-project/specs/systems/filecoin_blockchain/struct/block"

type ChainSync struct {
// LastTrustedCheckpoint is the most recent TrustedCheckpoint
// ChainSync is aware of. This is used as the starting point from
// which to synchronize the chain. (See block/checkpoints)
LastTrustedCheckpoint block.TrustedCheckpoint

// VGraph is the ValidationGraph ChainSync uses to track all
// Blocks and decide which blocks to validate, when.
VGraph ValidationGraph
}

type ValidationGraph struct {
// ChainStore is the ipld Datastore through which to load and store
// all Chain datastructures (Blocks, Messages, StateTrees, etc.)
ChainStore ipld.Store

// CacheChainStore is the ipld Datastore through which to load and store
// chain datastructures that may be temporary and may be garbage collected.
CacheChainStore ipld.Store

// Graph is a datastructure that provides efficient access to all
// nodes needed for validation, and keeps both forward and back links.
// Graph graph.BlockGraph

// FinalityTipset contains the latest finalized tipset -- this is the
// local node's notion of finality. It will not automatically unwind
// history before this point. All automatic ChainSync is forward from
// this tipset.
//
// This is what we use to check state against for users/clients of the
// blockchain subsystem. If users request FinalityEpoch, it corresponds
// to FinalityTipset.
FinalityTipset PartialGraph

// ValidG contains all the blocks we have validated, but are not
// yet declared Final. This means all the blocks connected into the
// main blockchain, but not yet past finality (ie after FinalityTipset)
ValidG PartialGraph

// FetchedG is the set of unvalidated Blocks fully connected
// to the validated graph. These are ready to be validated, all the
// data is local, and are ordered by total ChainWeight.
FetchedG PartialGraph

// ConnectedG is the set of connected Blocks (BlockHeaders) fully connected
// to the ToValidateG graph. These are close to ready to be validated.
// Data may or not may not be local. Ordered by total ChainWeight.
ConnectedG PartialGraph

// UnconnectedG is the set of connected Blocks (BlockHeaders), which
// may or may not connect back to the growing blockchain. This set
// could contain the heaviest chain, and could contain attackers'
// blocks.
UnconnectedG PartialGraph

// TargetHeads is a list of candidate blocks sorted by likelihood of being the
// best chain. (eg sorted by block.ChainWeight, even if not validated yet)
// TargetHeads SHOULD be a small set (<10)
//
// Obviously bad heads SHOULD be pruned out:
// - Clearly invalid ChainWeight (lower than BestHead or too high)
// - Heads that are not advancing in BlockPubsub
TargetHeads [block.BlockCID]
Copy link
Member

Choose a reason for hiding this comment

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

I have assumed all the way through here that "head" is a tipset, not a single block. This and BestTargetHead contradict that. I think we might need a new word to refer to blocks that area at the fringe (have no children), distinct from tipsets that can be composed from those blocks.

Copy link
Member Author

Choose a reason for hiding this comment

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

  • Yes -- sorry for the ambiguous word (head). maybe i should switch to TargetBlocks and BestTargetBlock
    • i can also rename in terms of Tipset, but thinking/dealing with them as tipsets is a bit trickier (combinatorics...)
  • I believe it is equivalent to do it in terms of Blocks (because each block uniquely defines a tipset, in the prior epoch, like the StateTree, and merely proposes messages for the next round) -- and it's easier to reason/program -- but this is flexible, can opt for what we prefer most
  • I think we might need a new word to refer to blocks that area at the fringe (have no children), distinct from tipsets that can be composed from those blocks.

  • yes, i was using "Head" that way -- maybe HeadBlock vs HeadTipset? hmmm open to other suggestions

Copy link
Member

Choose a reason for hiding this comment

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

I'm ok with most of this sync spec being phrased in terms of blocks. It does simplify a few things. But "head" in particular is ambiguous, so qualifying it always would help.

Copy link
Member Author

Choose a reason for hiding this comment

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

ok will do

Copy link
Member Author

Choose a reason for hiding this comment

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

addressed

Copy link
Member Author

Choose a reason for hiding this comment

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

(for now keeping word Head but clearly noting it is a block. may still switch it before PR lands.


// BestTargetHead is the single best candidate head
// BestTargetHead == TargetHeads[0]
BestTargetHead block.BlockCID
}

// PartialGraph is a datastructure used to track a set of blocks, and
// provide efficient access to the Roots/Heads and Leaves/Tails of the
// subgraph.
type PartialGraph struct {
// fullGraph provides acess to all nodes
fullGraph BlockGraph

// Blocks is the set of all blocks in this PartialGraph
Blocks {block.BlockCID: struct {}}

// Heads is the set of root/head blocks
Heads [block.BlockCID]

// Tails is the set of leaf/tail blocks
Tails [block.BlockCID]
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused. Does head refer to the newest thing, as in the "head of the chain" being the latest state? The use of "root" is confusing if so, since one might usually identify that with the genesis. Similarly "leaf" also sounds like the expanding fringe.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah this is an annoying nomenclature. this partial graph is a DAG fragment-- including disconnected components. here's a visual example, 4 example PartialGraphs, with Heads and Tails. (note they aren't tipsets)

image


// Add adds given BlockCID to the PartialGraph, updating Blocks,
// Roots, and Leaves as needed.
Add(c block.BlockCID)

// Remove deletes given BlockCID from the PartialGraph, updating
// Blocks, Roots, and Leaves as needed.
Remove(c block.BlockCID)
Copy link
Member

Choose a reason for hiding this comment

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

Is a graph necessarily connected, or is this just a bag of blocks, with each disconnected subgraph being reported in heads/tails?

Copy link
Member Author

Choose a reason for hiding this comment

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

is a graph necessarily connected, or is this jut a bag of blocks, with each disconnected subgraph being reported in heads/tails

the latter -- these are 4 examples of ParialGraphs, the 3rd and 4th case are separate chains.

image

}

type BlockGraph struct {// TODO
Parents(b block.BlockCID) block.Tipset
Children(b block.BlockCID) [block.Block]
}
58 changes: 58 additions & 0 deletions src/systems/filecoin_blockchain/chainsync/chainsync_fsm.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
digraph sector {
compound=true;
// splines=curved;
edge [style=solid]

{ // states
node [shape=box, fontname="monospace", style=filled, color=gray84]
INIT
BOOTSTRAP
SYNC_CHECKPOINT
CHAIN_CATCHUP
CHAIN_FOLLOW [color=seagreen3]
}

{ // transitions
node [shape=none]
init2boot [label=< <i>prepare and verify<br/>all internal state</i> >]
boot2check [label=< <i>done bootstrapping.<br/><b>DO NOT</b> have state for<br/><u>LastTrustedCheckpoint</u></i> >]
boot2catch [label=< <i>done bootstrapping.<br/><b>DO</b> have state for<br/><u>LastTrustedCheckpoint</u></i> >]
check2catch [label=< <i>done getting state for<br/><u>LastTrustedCheckpoint</u></i> >]
catch2follow [label=< <i>done validating<br/>up to <u>BestTargetHead</u></i> >]
{
follow2catch [label=< <i>new unvalidated gap between<br/><u>ValidG</u> and <u>BestTargetHead</u></i> >, constraint=false, color=red, fontcolor=red]
follow2init [label=< <i>on shut down node</i> >, constraint=false, color=red, fontcolor=red, pos="6,3!"]
}
}

{ // transition 1
edge [arrowhead=none]
INIT -> init2boot
BOOTSTRAP -> boot2check
BOOTSTRAP -> boot2catch
SYNC_CHECKPOINT -> check2catch
CHAIN_CATCHUP -> catch2follow
}

{ // transition 2
init2boot -> BOOTSTRAP
boot2check -> SYNC_CHECKPOINT
boot2catch -> CHAIN_CATCHUP
check2catch -> CHAIN_CATCHUP
catch2follow -> CHAIN_FOLLOW
}

{ // transition backs (reversed)
{
edge [dir=back]
CHAIN_CATCHUP -> follow2catch [color=red]
INIT -> follow2init [color=red]
}

{
edge [dir=none]
follow2catch -> CHAIN_FOLLOW [constraint=false, color=red]
// follow2init -> CHAIN_FOLLOW [color=red]
}
}
}
Loading