Skip to content

Commit

Permalink
Merge pull request #5336 from onflow/jordan/sync-dyn-proto-state--master
Browse files Browse the repository at this point in the history
Feature: Dynamic Protocol State
  • Loading branch information
jordanschalm authored Feb 1, 2024
2 parents 443ba43 + 321a9e2 commit 568129d
Show file tree
Hide file tree
Showing 390 changed files with 11,225 additions and 5,378 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
/cmd/util/util
/cmd/bootstrap/bootstrap

# Test ouput of bootstrapping CLI
cmd/bootstrap/bootstrap-example

# Test binary, build with `go test -c`
*.test
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ generate-fvm-env-wrappers:
generate-mocks: install-mock-generators
mockery --name '(Connector|PingInfoProvider)' --dir=network/p2p --case=underscore --output="./network/mocknetwork" --outpkg="mocknetwork"
CGO_CFLAGS=$(CRYPTO_FLAG) mockgen -destination=storage/mocks/storage.go -package=mocks github.com/onflow/flow-go/storage Blocks,Headers,Payloads,Collections,Commits,Events,ServiceEvents,TransactionResults
CGO_CFLAGS=$(CRYPTO_FLAG) mockgen -destination=module/mocks/network.go -package=mocks github.com/onflow/flow-go/module Local,Requester
# MERGE: Line below commented out on HEAD, uncommented on master
#CGO_CFLAGS=$(CRYPTO_FLAG) mockgen -destination=module/mocks/network.go -package=mocks github.com/onflow/flow-go/module Local,Requester
CGO_CFLAGS=$(CRYPTO_FLAG) mockgen -destination=network/mocknetwork/mock_network.go -package=mocknetwork github.com/onflow/flow-go/network EngineRegistry
mockery --name='.*' --dir=integration/benchmark/mocksiface --case=underscore --output="integration/benchmark/mock" --outpkg="mock"
mockery --name=ExecutionDataStore --dir=module/executiondatasync/execution_data --case=underscore --output="./module/executiondatasync/execution_data/mock" --outpkg="mock"
Expand All @@ -178,6 +179,7 @@ generate-mocks: install-mock-generators
mockery --name '.*' --dir=storage --case=underscore --output="./storage/mock" --outpkg="mock"
mockery --name '.*' --dir="state/protocol" --case=underscore --output="state/protocol/mock" --outpkg="mock"
mockery --name '.*' --dir="state/protocol/events" --case=underscore --output="./state/protocol/events/mock" --outpkg="mock"
mockery --name '.*' --dir="state/protocol/protocol_state" --case=underscore --output="state/protocol/protocol_state/mock" --outpkg="mock"
mockery --name '.*' --dir=engine/execution/computation/computer --case=underscore --output="./engine/execution/computation/computer/mock" --outpkg="mock"
mockery --name '.*' --dir=engine/execution/state --case=underscore --output="./engine/execution/state/mock" --outpkg="mock"
mockery --name '.*' --dir=engine/collection --case=underscore --output="./engine/collection/mock" --outpkg="mock"
Expand Down
6 changes: 3 additions & 3 deletions cmd/access/node_builder/access_node_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1240,8 +1240,8 @@ func (builder *FlowAccessNodeBuilder) InitIDProviders() {
builder.SyncEngineParticipantsProviderFactory = func() module.IdentifierProvider {
return id.NewIdentityFilterIdentifierProvider(
filter.And(
filter.HasRole(flow.RoleConsensus),
filter.Not(filter.HasNodeID(node.Me.NodeID())),
filter.HasRole[flow.Identity](flow.RoleConsensus),
filter.Not(filter.HasNodeID[flow.Identity](node.Me.NodeID())),
underlay.NotEjectedFilter,
),
builder.IdentityProvider,
Expand Down Expand Up @@ -1574,7 +1574,7 @@ func (builder *FlowAccessNodeBuilder) Build() (cmd.Node, error) {
node.Me,
node.State,
channels.RequestCollections,
filter.HasRole(flow.RoleCollection),
filter.HasRole[flow.Identity](flow.RoleCollection),
func() flow.Entity { return &flow.Collection{} },
)
if err != nil {
Expand Down
64 changes: 54 additions & 10 deletions cmd/bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,60 @@ Each input is a config file specified as a command line parameter:

#### Example
```bash
go run ./cmd/bootstrap finalize \
--root-chain main \
--root-height 0 \
--root-parent 0000000000000000000000000000000000000000000000000000000000000000 \
--root-commit 4b8d01975cf0cd23e046b1fae36518e542f92a6e35bedd627c43da30f4ae761a \
--config ./cmd/bootstrap/example_files/node-config.json \
--partner-dir ./cmd/bootstrap/example_files/partner-node-infos \
--partner-weights ./cmd/bootstrap/example_files/partner-weights.json \
--epoch-counter 1 \
-o ./bootstrap/root-infos
go run . genconfig \
--address-format "%s%d-example.onflow.org:3569" \
--access 2 \
--collection 4 \
--consensus 3 \
--execution 2 \
--verification 3 \
--weight 100 \
-o ./ \
--config ./bootstrap-example/node-config.json

```

```bash
go run . keygen \
--machine-account \
--config ./bootstrap-example/node-config.json \
-o ./bootstrap-example/keys

```

```bash
go run . rootblock \
--root-chain bench \
--root-height 0 \
--root-parent 0000000000000000000000000000000000000000000000000000000000000000 \
--epoch-counter 0 \
--epoch-length 30000 \
--epoch-staking-phase-length 20000 \
--epoch-dkg-phase-length 2000 \
--collection-clusters 1 \
--protocol-version=0 \
--epoch-commit-safety-threshold=1000 \
--config ./bootstrap-example/node-config.json \
-o ./bootstrap-example \
--partner-dir ./example_files/partner-node-infos \
--partner-weights ./example_files/partner-weights.json \
--internal-priv-dir ./bootstrap-example/keys
```

```bash
go run . finalize \
--config ./bootstrap-example/node-config.json \
--partner-dir ./example_files/partner-node-infos \
--partner-weights ./example_files/partner-weights.json \
--internal-priv-dir ./bootstrap-example/keys/private-root-information \
--dkg-data ./bootstrap-example/private-root-information/root-dkg-data.priv.json \
--root-block ./bootstrap-example/public-root-information/root-block.json \
--intermediary-bootstrapping-data ./bootstrap-example/public-root-information/intermediary-bootstrapping-data.json \
--root-block-votes-dir ./bootstrap-example/public-root-information/root-block-votes/ \
--root-commit 0000000000000000000000000000000000000000000000000000000000000000 \
--genesis-token-supply="1000000000.0" \
--service-account-public-key-json "{\"PublicKey\":\"R7MTEDdLclRLrj2MI1hcp4ucgRTpR15PCHAWLM5nks6Y3H7+PGkfZTP2di2jbITooWO4DD1yqaBSAVK8iQ6i0A==\",\"SignAlgo\":2,\"HashAlgo\":1,\"SeqNumber\":0,\"Weight\":1000}" \
-o ./bootstrap-example
```

#### Generated output files
Expand Down
66 changes: 63 additions & 3 deletions cmd/bootstrap/cmd/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,81 @@ import (
"time"

"github.com/onflow/flow-go/cmd/bootstrap/run"
"github.com/onflow/flow-go/model/dkg"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/module/signature"
"github.com/onflow/flow-go/state/protocol/inmem"
)

func constructRootBlock(rootChain string, rootParent string, rootHeight uint64, rootTimestamp string) *flow.Block {

// constructRootHeader constructs a header for the root block.
func constructRootHeader(rootChain string, rootParent string, rootHeight uint64, rootTimestamp string) *flow.Header {
chainID := parseChainID(rootChain)
parentID := parseParentID(rootParent)
height := rootHeight
timestamp := parseRootTimestamp(rootTimestamp)

block := run.GenerateRootBlock(chainID, parentID, height, timestamp)
return run.GenerateRootHeader(chainID, parentID, height, timestamp)
}

// constructRootBlock constructs a valid root block based on the given header, setup, and commit.
func constructRootBlock(rootHeader *flow.Header, setup *flow.EpochSetup, commit *flow.EpochCommit) *flow.Block {
block := &flow.Block{
Header: rootHeader,
Payload: nil,
}
block.SetPayload(flow.Payload{
Guarantees: nil,
Seals: nil,
Receipts: nil,
Results: nil,
ProtocolStateID: inmem.ProtocolStateFromEpochServiceEvents(setup, commit).ID(),
})
return block
}

// constructRootEpochEvents constructs the epoch setup and commit events for the first epoch after spork.
func constructRootEpochEvents(
firstView uint64,
participants flow.IdentityList,
assignments flow.AssignmentList,
clusterQCs []*flow.QuorumCertificate,
dkgData dkg.DKGData) (*flow.EpochSetup, *flow.EpochCommit) {
epochSetup := &flow.EpochSetup{
Counter: flagEpochCounter,
FirstView: firstView,
FinalView: firstView + flagNumViewsInEpoch - 1,
DKGPhase1FinalView: firstView + flagNumViewsInStakingAuction + flagNumViewsInDKGPhase - 1,
DKGPhase2FinalView: firstView + flagNumViewsInStakingAuction + flagNumViewsInDKGPhase*2 - 1,
DKGPhase3FinalView: firstView + flagNumViewsInStakingAuction + flagNumViewsInDKGPhase*3 - 1,
Participants: participants.Sort(flow.Canonical[flow.Identity]).ToSkeleton(),
Assignments: assignments,
RandomSource: GenerateRandomSeed(flow.EpochSetupRandomSourceLength),
}

qcsWithSignerIDs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(clusterQCs))
for i, clusterQC := range clusterQCs {
members := assignments[i]
signerIDs, err := signature.DecodeSignerIndicesToIdentifiers(members, clusterQC.SignerIndices)
if err != nil {
log.Fatal().Err(err).Msgf("could not decode signer IDs from clusterQC at index %v", i)
}
qcsWithSignerIDs = append(qcsWithSignerIDs, &flow.QuorumCertificateWithSignerIDs{
View: clusterQC.View,
BlockID: clusterQC.BlockID,
SignerIDs: signerIDs,
SigData: clusterQC.SigData,
})
}

epochCommit := &flow.EpochCommit{
Counter: flagEpochCounter,
ClusterQCs: flow.ClusterQCVoteDatasFromQCs(qcsWithSignerIDs),
DKGGroupKey: dkgData.PubGroupKey,
DKGParticipantKeys: dkgData.PubKeyShares,
}
return epochSetup, epochCommit
}

func parseChainID(chainID string) flow.ChainID {
switch chainID {
case "main":
Expand Down
8 changes: 4 additions & 4 deletions cmd/bootstrap/cmd/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (
// of succeeding the assignment by re-running the function without increasing the internal nodes ratio.
func constructClusterAssignment(partnerNodes, internalNodes []model.NodeInfo) (flow.AssignmentList, flow.ClusterList, error) {

partners := model.ToIdentityList(partnerNodes).Filter(filter.HasRole(flow.RoleCollection))
internals := model.ToIdentityList(internalNodes).Filter(filter.HasRole(flow.RoleCollection))
partners := model.ToIdentityList(partnerNodes).Filter(filter.HasRole[flow.Identity](flow.RoleCollection))
internals := model.ToIdentityList(internalNodes).Filter(filter.HasRole[flow.Identity](flow.RoleCollection))
nClusters := int(flagCollectionClusters)
nCollectors := len(partners) + len(internals)

Expand Down Expand Up @@ -73,7 +73,7 @@ func constructClusterAssignment(partnerNodes, internalNodes []model.NodeInfo) (f
assignments := assignment.FromIdentifierLists(identifierLists)

collectors := append(partners, internals...)
clusters, err := factory.NewClusterList(assignments, collectors)
clusters, err := factory.NewClusterList(assignments, collectors.ToSkeleton())
if err != nil {
log.Fatal().Err(err).Msg("could not create cluster list")
}
Expand Down Expand Up @@ -109,7 +109,7 @@ func constructRootQCsForClusters(
// Filters a list of nodes to include only nodes that will sign the QC for the
// given cluster. The resulting list of nodes is only nodes that are in the
// given cluster AND are not partner nodes (ie. we have the private keys).
func filterClusterSigners(cluster flow.IdentityList, nodeInfos []model.NodeInfo) []model.NodeInfo {
func filterClusterSigners(cluster flow.IdentitySkeletonList, nodeInfos []model.NodeInfo) []model.NodeInfo {

var filtered []model.NodeInfo
for _, node := range nodeInfos {
Expand Down
8 changes: 4 additions & 4 deletions cmd/bootstrap/cmd/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import (
func ensureUniformNodeWeightsPerRole(allNodes flow.IdentityList) {
// ensure all nodes of the same role have equal weight
for _, role := range flow.Roles() {
withRole := allNodes.Filter(filter.HasRole(role))
withRole := allNodes.Filter(filter.HasRole[flow.Identity](role))
// each role has at least one node so it's safe to access withRole[0]
expectedWeight := withRole[0].Weight
expectedWeight := withRole[0].InitialWeight
for _, node := range withRole {
if node.Weight != expectedWeight {
if node.InitialWeight != expectedWeight {
log.Fatal().Msgf(
"will not bootstrap configuration with non-equal weights\n"+
"found nodes with role %s and weight1=%d, weight2=%d",
role, expectedWeight, node.Weight)
role, expectedWeight, node.InitialWeight)
}
}
}
Expand Down
Loading

0 comments on commit 568129d

Please sign in to comment.