Skip to content

Commit

Permalink
Merge branch 'master' into yahya/rpc-inspector-doc
Browse files Browse the repository at this point in the history
  • Loading branch information
thep2p authored Feb 15, 2024
2 parents 09c50d2 + ae8ab05 commit b556ae4
Show file tree
Hide file tree
Showing 130 changed files with 5,323 additions and 2,344 deletions.
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,6 @@ 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
# 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 Down
95 changes: 62 additions & 33 deletions cmd/access/node_builder/access_node_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,36 +120,37 @@ import (
// For a node running as a standalone process, the config fields will be populated from the command line params,
// while for a node running as a library, the config fields are expected to be initialized by the caller.
type AccessNodeConfig struct {
supportsObserver bool // True if this is an Access node that supports observers and consensus follower engines
collectionGRPCPort uint
executionGRPCPort uint
pingEnabled bool
nodeInfoFile string
apiRatelimits map[string]int
apiBurstlimits map[string]int
rpcConf rpc.Config
stateStreamConf statestreambackend.Config
stateStreamFilterConf map[string]int
ExecutionNodeAddress string // deprecated
HistoricalAccessRPCs []access.AccessAPIClient
logTxTimeToFinalized bool
logTxTimeToExecuted bool
logTxTimeToFinalizedExecuted bool
retryEnabled bool
rpcMetricsEnabled bool
executionDataSyncEnabled bool
executionDataDir string
executionDataStartHeight uint64
executionDataConfig edrequester.ExecutionDataConfig
PublicNetworkConfig PublicNetworkConfig
TxResultCacheSize uint
TxErrorMessagesCacheSize uint
executionDataIndexingEnabled bool
registersDBPath string
checkpointFile string
scriptExecutorConfig query.QueryConfig
scriptExecMinBlock uint64
scriptExecMaxBlock uint64
supportsObserver bool // True if this is an Access node that supports observers and consensus follower engines
collectionGRPCPort uint
executionGRPCPort uint
pingEnabled bool
nodeInfoFile string
apiRatelimits map[string]int
apiBurstlimits map[string]int
rpcConf rpc.Config
stateStreamConf statestreambackend.Config
stateStreamFilterConf map[string]int
ExecutionNodeAddress string // deprecated
HistoricalAccessRPCs []access.AccessAPIClient
logTxTimeToFinalized bool
logTxTimeToExecuted bool
logTxTimeToFinalizedExecuted bool
retryEnabled bool
rpcMetricsEnabled bool
executionDataSyncEnabled bool
publicNetworkExecutionDataEnabled bool
executionDataDir string
executionDataStartHeight uint64
executionDataConfig edrequester.ExecutionDataConfig
PublicNetworkConfig PublicNetworkConfig
TxResultCacheSize uint
TxErrorMessagesCacheSize uint
executionDataIndexingEnabled bool
registersDBPath string
checkpointFile string
scriptExecutorConfig query.QueryConfig
scriptExecMinBlock uint64
scriptExecMaxBlock uint64
}

type PublicNetworkConfig struct {
Expand Down Expand Up @@ -225,9 +226,10 @@ func DefaultAccessNodeConfig() *AccessNodeConfig {
BindAddress: cmd.NotSet,
Metrics: metrics.NewNoopCollector(),
},
executionDataSyncEnabled: true,
executionDataDir: filepath.Join(homedir, ".flow", "execution_data"),
executionDataStartHeight: 0,
executionDataSyncEnabled: true,
publicNetworkExecutionDataEnabled: false,
executionDataDir: filepath.Join(homedir, ".flow", "execution_data"),
executionDataStartHeight: 0,
executionDataConfig: edrequester.ExecutionDataConfig{
InitialBlockHeight: 0,
MaxSearchAhead: edrequester.DefaultMaxSearchAhead,
Expand Down Expand Up @@ -272,6 +274,7 @@ type FlowAccessNodeBuilder struct {
FollowerCore module.HotStuffFollower
Validator hotstuff.Validator
ExecutionDataDownloader execution_data.Downloader
PublicBlobService network.BlobService
ExecutionDataRequester state_synchronization.ExecutionDataRequester
ExecutionDataStore execution_data.ExecutionDataStore
ExecutionDataCache *execdatacache.ExecutionDataCache
Expand Down Expand Up @@ -664,6 +667,28 @@ func (builder *FlowAccessNodeBuilder) BuildExecutionSyncComponents() *FlowAccess
return builder.ExecutionDataRequester, nil
})

if builder.publicNetworkExecutionDataEnabled {
builder.Component("public network execution data service", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) {
opts := []network.BlobServiceOption{
blob.WithBitswapOptions(
bitswap.WithTracer(
blob.NewTracer(node.Logger.With().Str("public_blob_service", channels.PublicExecutionDataService.String()).Logger()),
),
),
}

net := builder.AccessNodeConfig.PublicNetworkConfig.Network

var err error
builder.PublicBlobService, err = net.RegisterBlobService(channels.PublicExecutionDataService, ds, opts...)
if err != nil {
return nil, fmt.Errorf("could not register blob service: %w", err)
}

return builder.PublicBlobService, nil
})
}

if builder.executionDataIndexingEnabled {
var indexedBlockHeight storage.ConsumerProgress

Expand Down Expand Up @@ -1029,6 +1054,10 @@ func (builder *FlowAccessNodeBuilder) extraFlags() {
"execution-data-sync-enabled",
defaultConfig.executionDataSyncEnabled,
"whether to enable the execution data sync protocol")
flags.BoolVar(&builder.publicNetworkExecutionDataEnabled,
"public-network-execution-data-sync-enabled",
defaultConfig.publicNetworkExecutionDataEnabled,
"[experimental] whether to enable the execution data sync protocol on public network")
flags.StringVar(&builder.executionDataDir, "execution-data-dir", defaultConfig.executionDataDir, "directory to use for Execution Data database")
flags.Uint64Var(&builder.executionDataStartHeight,
"execution-data-start-height",
Expand Down
1 change: 1 addition & 0 deletions cmd/bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ go run . rootblock \
--epoch-dkg-phase-length 2000 \
--collection-clusters 1 \
--protocol-version=0 \
--use-default-epoch-timing \
--epoch-commit-safety-threshold=1000 \
--config ./bootstrap-example/node-config.json \
-o ./bootstrap-example \
Expand Down
2 changes: 2 additions & 0 deletions cmd/bootstrap/cmd/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func constructRootEpochEvents(
Participants: participants.Sort(flow.Canonical[flow.Identity]).ToSkeleton(),
Assignments: assignments,
RandomSource: GenerateRandomSeed(flow.EpochSetupRandomSourceLength),
TargetDuration: flagEpochTimingDuration,
TargetEndTime: rootEpochTargetEndTime(),
}

qcsWithSignerIDs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(clusterQCs))
Expand Down
51 changes: 47 additions & 4 deletions cmd/bootstrap/cmd/finalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"path/filepath"
"strings"
"time"

"github.com/onflow/cadence"

Expand Down Expand Up @@ -121,7 +122,7 @@ func finalize(cmd *cobra.Command, args []string) {
internalNodes := readInternalNodeInfos()
log.Info().Msg("")

log.Info().Msg("checking constraints on consensus/cluster nodes")
log.Info().Msg("checking constraints on consensus nodes")
checkConstraints(partnerNodes, internalNodes)
log.Info().Msg("")

Expand Down Expand Up @@ -162,7 +163,7 @@ func finalize(cmd *cobra.Command, args []string) {
// if no root commit is specified, bootstrap an empty execution state
if flagRootCommit == "0000000000000000000000000000000000000000000000000000000000000000" {
commit := generateEmptyExecutionState(
block.Header.ChainID,
block.Header,
intermediaryData.ExecutionStateConfig,
participants,
)
Expand Down Expand Up @@ -557,7 +558,7 @@ func readIntermediaryBootstrappingData() (*IntermediaryBootstrappingData, *flow.
// generateEmptyExecutionState generates a new empty execution state with the
// given configuration. Sets the flagRootCommit variable for future reads.
func generateEmptyExecutionState(
chainID flow.ChainID,
rootBlock *flow.Header,
epochConfig epochs.EpochConfig,
identities flow.IdentityList,
) (commit flow.StateCommitment) {
Expand All @@ -577,7 +578,8 @@ func generateEmptyExecutionState(
commit, err = run.GenerateExecutionState(
filepath.Join(flagOutdir, model.DirnameExecutionState),
serviceAccountPublicKey,
chainID.Chain(),
rootBlock.ChainID.Chain(),
fvm.WithRootBlock(rootBlock),
fvm.WithInitialTokenSupply(cdcInitialTokenSupply),
fvm.WithMinimumStorageReservation(fvm.DefaultMinimumStorageReservation),
fvm.WithAccountCreationFee(fvm.DefaultAccountCreationFee),
Expand All @@ -591,3 +593,44 @@ func generateEmptyExecutionState(
log.Info().Msg("")
return commit
}

// validateOrPopulateEpochTimingConfig validates the epoch timing config flags. In case the
// `flagUseDefaultEpochTargetEndTime` value has been set, the function derives the values for
// `flagEpochTimingRefCounter`, `flagEpochTimingDuration`, and `flagEpochTimingRefTimestamp`
// from the configuration. Otherwise, it enforces that compatible values for the respective parameters have been
// specified (and errors otherwise). Therefore, after `validateOrPopulateEpochTimingConfig` ran,
// the targeted end time for the epoch can be computed via `rootEpochTargetEndTime()`.
// You can either let the tool choose default values, or specify a value for each config.
func validateOrPopulateEpochTimingConfig() error {
// Default timing is intended for Benchnet, Localnet, etc.
// Manually specified timings for Mainnet, Testnet, Canary.
if flagUseDefaultEpochTargetEndTime {
// No other flags may be set
if !(flagEpochTimingRefTimestamp == 0 && flagEpochTimingDuration == 0 && flagEpochTimingRefCounter == 0) {
return fmt.Errorf("invalid epoch timing config: cannot specify ANY of --epoch-timing-ref-counter, --epoch-timing-ref-timestamp, or --epoch-timing-duration if using default timing config")
}
flagEpochTimingRefCounter = flagEpochCounter
flagEpochTimingDuration = flagNumViewsInEpoch
flagEpochTimingRefTimestamp = uint64(time.Now().Unix()) + flagNumViewsInEpoch

// compute target end time for initial (root) epoch from flags: `TargetEndTime = RefTimestamp + (RootEpochCounter - RefEpochCounter) * Duration`
rootEpochTargetEndTimeUNIX := rootEpochTargetEndTime()
rootEpochTargetEndTime := time.Unix(int64(rootEpochTargetEndTimeUNIX), 0)
log.Info().Msgf("using default epoch timing config with root epoch target end time %s, which is in %s", rootEpochTargetEndTime, time.Until(rootEpochTargetEndTime))
} else {
// All other flags must be set
// NOTE: it is valid for flagEpochTimingRefCounter to be set to 0
if flagEpochTimingRefTimestamp == 0 || flagEpochTimingDuration == 0 {
return fmt.Errorf("invalid epoch timing config: must specify ALL of --epoch-timing-ref-counter, --epoch-timing-ref-timestamp, and --epoch-timing-duration")
}
if flagEpochCounter < flagEpochTimingRefCounter {
return fmt.Errorf("invalid epoch timing config: reference epoch counter must be less than or equal to root epoch counter")
}

// compute target end time for initial (root) epoch from flags: `TargetEndTime = RefTimestamp + (RootEpochCounter - RefEpochCounter) * Duration`
rootEpochTargetEndTimeUNIX := rootEpochTargetEndTime()
rootEpochTargetEndTime := time.Unix(int64(rootEpochTargetEndTimeUNIX), 0)
log.Info().Msgf("using user-specified epoch timing config with root epoch target end time %s, which is in %s", rootEpochTargetEndTime, time.Until(rootEpochTargetEndTime))
}
return nil
}
52 changes: 51 additions & 1 deletion cmd/bootstrap/cmd/finalize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package cmd

import (
"encoding/hex"
"fmt"
"math/rand"
"path/filepath"
"regexp"
"strings"
Expand All @@ -23,7 +25,7 @@ const finalizeHappyPathLogs = "collecting partner network and staking keys" +
`read \d+ internal private node-info files` +
`read internal node configurations` +
`read \d+ weights for internal nodes` +
`checking constraints on consensus/cluster nodes` +
`checking constraints on consensus nodes` +
`assembling network and staking keys` +
`reading root block data` +
`reading root block votes` +
Expand Down Expand Up @@ -72,6 +74,10 @@ func TestFinalize_HappyPath(t *testing.T) {
flagNumViewsInStakingAuction = 50_000
flagNumViewsInDKGPhase = 2_000
flagEpochCommitSafetyThreshold = 1_000
flagUseDefaultEpochTargetEndTime = true
flagEpochTimingRefCounter = 0
flagEpochTimingRefTimestamp = 0
flagEpochTimingDuration = 0

// rootBlock will generate DKG and place it into bootDir/public-root-information
rootBlock(nil, nil)
Expand All @@ -85,6 +91,7 @@ func TestFinalize_HappyPath(t *testing.T) {
log = log.Hook(hook)

finalize(nil, nil)
fmt.Println(hook.logs.String())
assert.Regexp(t, finalizeHappyPathRegex, hook.logs.String())
hook.logs.Reset()

Expand Down Expand Up @@ -117,6 +124,49 @@ func TestClusterAssignment(t *testing.T) {
flagCollectionClusters = tmp
}

func TestEpochTimingConfig(t *testing.T) {
// Reset flags after test is completed
defer func(_flagDefault bool, _flagRefCounter, _flagRefTs, _flagDur uint64) {
flagUseDefaultEpochTargetEndTime = _flagDefault
flagEpochTimingRefCounter = _flagRefCounter
flagEpochTimingRefTimestamp = _flagRefTs
flagEpochTimingDuration = _flagDur
}(flagUseDefaultEpochTargetEndTime, flagEpochTimingRefCounter, flagEpochTimingRefTimestamp, flagEpochTimingDuration)

flags := []*uint64{&flagEpochTimingRefCounter, &flagEpochTimingRefTimestamp, &flagEpochTimingDuration}
t.Run("if default is set, no other flag may be set", func(t *testing.T) {
flagUseDefaultEpochTargetEndTime = true
for _, flag := range flags {
*flag = rand.Uint64()%100 + 1
err := validateOrPopulateEpochTimingConfig()
assert.Error(t, err)
*flag = 0 // set the flag back to 0
}
err := validateOrPopulateEpochTimingConfig()
assert.NoError(t, err)
})

t.Run("if default is not set, all other flags must be set", func(t *testing.T) {
flagUseDefaultEpochTargetEndTime = false
// First set all required flags and ensure validation passes
flagEpochTimingRefCounter = rand.Uint64() % flagEpochCounter
flagEpochTimingDuration = rand.Uint64()%100_000 + 1
flagEpochTimingRefTimestamp = rand.Uint64()

err := validateOrPopulateEpochTimingConfig()
assert.NoError(t, err)

// Next, check that validation fails if any one flag is not set
// NOTE: we do not include refCounter here, because it is allowed to be zero.
for _, flag := range []*uint64{&flagEpochTimingRefTimestamp, &flagEpochTimingDuration} {
*flag = 0
err := validateOrPopulateEpochTimingConfig()
assert.Error(t, err)
*flag = rand.Uint64()%100 + 1 // set the flag back to a non-zero value
}
})
}

// Check about the number of internal/partner nodes in each cluster. The identites
// in each cluster do not matter for this check.
func checkClusterConstraint(clusters flow.ClusterList, partnersInfo []model.NodeInfo, internalsInfo []model.NodeInfo) bool {
Expand Down
28 changes: 28 additions & 0 deletions cmd/bootstrap/cmd/rootblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ var (
flagNumViewsInEpoch uint64
flagNumViewsInStakingAuction uint64
flagNumViewsInDKGPhase uint64
// Epoch target end time config
flagUseDefaultEpochTargetEndTime bool
flagEpochTimingRefCounter uint64
flagEpochTimingRefTimestamp uint64
flagEpochTimingDuration uint64
)

// rootBlockCmd represents the rootBlock command
Expand Down Expand Up @@ -95,6 +100,25 @@ func addRootBlockCmdFlags() {
cmd.MarkFlagRequired(rootBlockCmd, "root-height")
cmd.MarkFlagRequired(rootBlockCmd, "protocol-version")
cmd.MarkFlagRequired(rootBlockCmd, "epoch-commit-safety-threshold")

// Epoch timing config - these values must be set identically to `EpochTimingConfig` in the FlowEpoch smart contract.
// See https://github.com/onflow/flow-core-contracts/blob/240579784e9bb8d97d91d0e3213614e25562c078/contracts/epochs/FlowEpoch.cdc#L259-L266
// Must specify either:
// 1. --use-default-epoch-timing and no other `--epoch-timing*` flags
// 2. All `--epoch-timing*` flags except --use-default-epoch-timing
//
// Use Option 1 for Benchnet, Localnet, etc.
// Use Option 2 for Mainnet, Testnet, Canary.
rootBlockCmd.Flags().BoolVar(&flagUseDefaultEpochTargetEndTime, "use-default-epoch-timing", false, "whether to use the default target end time")
rootBlockCmd.Flags().Uint64Var(&flagEpochTimingRefCounter, "epoch-timing-ref-counter", 0, "the reference epoch for computing the root epoch's target end time")
rootBlockCmd.Flags().Uint64Var(&flagEpochTimingRefTimestamp, "epoch-timing-ref-timestamp", 0, "the end time of the reference epoch, specified in second-precision Unix time, to use to compute the root epoch's target end time")
rootBlockCmd.Flags().Uint64Var(&flagEpochTimingDuration, "epoch-timing-duration", 0, "the duration of each epoch in seconds, used to compute the root epoch's target end time")

rootBlockCmd.MarkFlagsOneRequired("use-default-epoch-timing", "epoch-timing-ref-counter", "epoch-timing-ref-timestamp", "epoch-timing-duration")
rootBlockCmd.MarkFlagsRequiredTogether("epoch-timing-ref-counter", "epoch-timing-ref-timestamp", "epoch-timing-duration")
for _, flag := range []string{"epoch-timing-ref-counter", "epoch-timing-ref-timestamp", "epoch-timing-duration"} {
rootBlockCmd.MarkFlagsMutuallyExclusive("use-default-epoch-timing", flag)
}
}

func rootBlock(cmd *cobra.Command, args []string) {
Expand All @@ -114,6 +138,10 @@ func rootBlock(cmd *cobra.Command, args []string) {
if err != nil {
log.Fatal().Err(err).Msg("invalid or unsafe epoch commit threshold config")
}
err = validateOrPopulateEpochTimingConfig()
if err != nil {
log.Fatal().Err(err).Msg("invalid epoch timing config")
}

log.Info().Msg("collecting partner network and staking keys")
partnerNodes := readPartnerNodeInfos()
Expand Down
4 changes: 4 additions & 0 deletions cmd/bootstrap/cmd/rootblock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func TestRootBlock_HappyPath(t *testing.T) {
flagNumViewsInDKGPhase = 2_000
flagEpochCommitSafetyThreshold = 1_000
flagProtocolVersion = 42
flagUseDefaultEpochTargetEndTime = true
flagEpochTimingRefCounter = 0
flagEpochTimingRefTimestamp = 0
flagEpochTimingDuration = 0

hook := zeroLoggerHook{logs: &strings.Builder{}}
log = log.Hook(hook)
Expand Down
Loading

0 comments on commit b556ae4

Please sign in to comment.