github.com/onflow/flow-go@v0.33.17/fvm/bootstrap.go (about)

     1  package fvm
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  
     7  	"github.com/onflow/cadence"
     8  	"github.com/onflow/flow-core-contracts/lib/go/contracts"
     9  
    10  	"github.com/onflow/flow-go/fvm/blueprints"
    11  	"github.com/onflow/flow-go/fvm/environment"
    12  	"github.com/onflow/flow-go/fvm/errors"
    13  	"github.com/onflow/flow-go/fvm/evm/stdlib"
    14  	"github.com/onflow/flow-go/fvm/meter"
    15  	"github.com/onflow/flow-go/fvm/storage"
    16  	"github.com/onflow/flow-go/fvm/storage/logical"
    17  	"github.com/onflow/flow-go/model/flow"
    18  	"github.com/onflow/flow-go/module/epochs"
    19  )
    20  
    21  var (
    22  	DefaultAccountCreationFee = mustParseUFix64(
    23  		"account creation fee",
    24  		"0.00100000")
    25  
    26  	DefaultMinimumStorageReservation = mustParseUFix64(
    27  		"minimum storage reservation",
    28  		"0.00100000")
    29  
    30  	DefaultStorageMBPerFLOW = mustParseUFix64(
    31  		"storage mb per flow",
    32  		"100.00000000")
    33  
    34  	// DefaultTransactionFees are the default transaction fee parameters if
    35  	// transaction fees are on. Surge factor is 1.0, inclusion effort cost is
    36  	// 0.0001 (because the static inclusion effort is 1.0) and execution effort
    37  	// cost is 0.0 because dynamic execution fees are off. If they are off
    38  	// (which is the default behaviour) that means the transaction fees are 0.0.
    39  	DefaultTransactionFees = BootstrapProcedureFeeParameters{
    40  		SurgeFactor: mustParseUFix64("fee surge factor", "1.0"),
    41  		InclusionEffortCost: mustParseUFix64(
    42  			"fee inclusion effort cost",
    43  			"0.00001"),
    44  		ExecutionEffortCost: mustParseUFix64(
    45  			"fee execution effort cost",
    46  			"0.0"),
    47  	}
    48  
    49  	// DefaultVersionFreezePeriod is the default NodeVersionBeacon freeze period -
    50  	// the number of blocks in the future where the version changes are frozen.
    51  	DefaultVersionFreezePeriod = cadence.UInt64(1000)
    52  )
    53  
    54  func mustParseUFix64(name string, valueString string) cadence.UFix64 {
    55  	value, err := cadence.NewUFix64(valueString)
    56  	if err != nil {
    57  		panic(fmt.Errorf("invalid default %s: %w", name, err))
    58  	}
    59  	return value
    60  }
    61  
    62  // A BootstrapProcedure is an invokable that can be used to bootstrap the ledger state
    63  // with the default accounts and contracts required by the Flow virtual machine.
    64  type BootstrapProcedure struct {
    65  	BootstrapParams
    66  }
    67  
    68  type BootstrapParams struct {
    69  	rootBlock *flow.Header
    70  
    71  	// genesis parameters
    72  	accountKeys        BootstrapAccountKeys
    73  	initialTokenSupply cadence.UFix64
    74  
    75  	accountCreationFee               cadence.UFix64
    76  	minimumStorageReservation        cadence.UFix64
    77  	storagePerFlow                   cadence.UFix64
    78  	restrictedAccountCreationEnabled cadence.Bool
    79  
    80  	// `setupEVMEnabled` == true && `evmAbiOnly` == true will enable the ABI-only EVM
    81  	// `setupEVMEnabled` == true && `evmAbiOnly` == false will enable the full EVM functionality
    82  	// `setupEVMEnabled` == false will disable EVM
    83  	// This will allow to quickly disable the ABI-only EVM, in case there's a bug or something.
    84  	setupEVMEnabled cadence.Bool
    85  	evmAbiOnly      cadence.Bool
    86  
    87  	// versionFreezePeriod is the number of blocks in the future where the version
    88  	// changes are frozen. The Node version beacon manages the freeze period,
    89  	// but this is the value used when first deploying the contract, during the
    90  	// bootstrap procedure.
    91  	versionFreezePeriod cadence.UInt64
    92  
    93  	// TODO: restrictedContractDeployment should be a bool after RestrictedDeploymentEnabled is removed from the context
    94  	// restrictedContractDeployment of nil means that the contract deployment is taken from the fvm Context instead of from the state.
    95  	// This can be used to mimic behaviour on chain before the restrictedContractDeployment is set with a service account transaction.
    96  	restrictedContractDeployment *bool
    97  
    98  	transactionFees        BootstrapProcedureFeeParameters
    99  	executionEffortWeights meter.ExecutionEffortWeights
   100  	executionMemoryWeights meter.ExecutionMemoryWeights
   101  	// executionMemoryLimit of 0 means that it won't be set in the state. The FVM will use the default value from the context.
   102  	executionMemoryLimit uint64
   103  
   104  	// config values for epoch smart-contracts
   105  	epochConfig epochs.EpochConfig
   106  
   107  	// list of initial network participants for whom we will create/stake flow
   108  	// accounts and retrieve epoch-related resources
   109  	identities flow.IdentityList
   110  }
   111  
   112  type BootstrapAccountKeys struct {
   113  	ServiceAccountPublicKeys       []flow.AccountPublicKey
   114  	FungibleTokenAccountPublicKeys []flow.AccountPublicKey
   115  	FlowTokenAccountPublicKeys     []flow.AccountPublicKey
   116  	FlowFeesAccountPublicKeys      []flow.AccountPublicKey
   117  	NodeAccountPublicKeys          []flow.AccountPublicKey
   118  }
   119  
   120  type BootstrapProcedureFeeParameters struct {
   121  	SurgeFactor         cadence.UFix64
   122  	InclusionEffortCost cadence.UFix64
   123  	ExecutionEffortCost cadence.UFix64
   124  }
   125  
   126  type BootstrapProcedureOption func(*BootstrapProcedure) *BootstrapProcedure
   127  
   128  func WithInitialTokenSupply(supply cadence.UFix64) BootstrapProcedureOption {
   129  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   130  		bp.initialTokenSupply = supply
   131  		return bp
   132  	}
   133  }
   134  
   135  // WithBootstrapAccountKeys sets the public keys of the accounts that will be created during bootstrapping
   136  // by default all accounts are created with the ServiceAccountPublicKey specified when calling `Bootstrap`.
   137  func WithBootstrapAccountKeys(keys BootstrapAccountKeys) BootstrapProcedureOption {
   138  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   139  		bp.accountKeys = keys
   140  		return bp
   141  	}
   142  }
   143  
   144  func WithAccountCreationFee(fee cadence.UFix64) BootstrapProcedureOption {
   145  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   146  		bp.accountCreationFee = fee
   147  		return bp
   148  	}
   149  }
   150  
   151  func WithTransactionFee(fees BootstrapProcedureFeeParameters) BootstrapProcedureOption {
   152  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   153  		bp.transactionFees = fees
   154  		return bp
   155  	}
   156  }
   157  
   158  func WithExecutionEffortWeights(weights meter.ExecutionEffortWeights) BootstrapProcedureOption {
   159  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   160  		bp.executionEffortWeights = weights
   161  		return bp
   162  	}
   163  }
   164  
   165  func WithExecutionMemoryWeights(weights meter.ExecutionMemoryWeights) BootstrapProcedureOption {
   166  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   167  		bp.executionMemoryWeights = weights
   168  		return bp
   169  	}
   170  }
   171  
   172  func WithExecutionMemoryLimit(limit uint64) BootstrapProcedureOption {
   173  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   174  		bp.executionMemoryLimit = limit
   175  		return bp
   176  	}
   177  }
   178  
   179  func WithMinimumStorageReservation(reservation cadence.UFix64) BootstrapProcedureOption {
   180  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   181  		bp.minimumStorageReservation = reservation
   182  		return bp
   183  	}
   184  }
   185  
   186  func WithEpochConfig(epochConfig epochs.EpochConfig) BootstrapProcedureOption {
   187  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   188  		bp.epochConfig = epochConfig
   189  		return bp
   190  	}
   191  }
   192  
   193  func WithRootBlock(rootBlock *flow.Header) BootstrapProcedureOption {
   194  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   195  		bp.rootBlock = rootBlock
   196  		return bp
   197  	}
   198  }
   199  
   200  func WithIdentities(identities flow.IdentityList) BootstrapProcedureOption {
   201  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   202  		bp.identities = identities
   203  		return bp
   204  	}
   205  }
   206  
   207  func WithStorageMBPerFLOW(ratio cadence.UFix64) BootstrapProcedureOption {
   208  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   209  		bp.storagePerFlow = ratio
   210  		return bp
   211  	}
   212  }
   213  
   214  func WithRestrictedAccountCreationEnabled(enabled cadence.Bool) BootstrapProcedureOption {
   215  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   216  		bp.restrictedAccountCreationEnabled = enabled
   217  		return bp
   218  	}
   219  }
   220  
   221  func WithSetupEVMEnabled(enabled cadence.Bool) BootstrapProcedureOption {
   222  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   223  		bp.setupEVMEnabled = enabled
   224  		return bp
   225  	}
   226  }
   227  
   228  func WithEVMABIOnly(evmAbiOnly cadence.Bool) BootstrapProcedureOption {
   229  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   230  		bp.evmAbiOnly = evmAbiOnly
   231  		return bp
   232  	}
   233  }
   234  
   235  func WithRestrictedContractDeployment(restricted *bool) BootstrapProcedureOption {
   236  	return func(bp *BootstrapProcedure) *BootstrapProcedure {
   237  		bp.restrictedContractDeployment = restricted
   238  		return bp
   239  	}
   240  }
   241  
   242  // Bootstrap returns a new BootstrapProcedure instance configured with the provided
   243  // genesis parameters.
   244  func Bootstrap(
   245  	serviceAccountPublicKey flow.AccountPublicKey,
   246  	opts ...BootstrapProcedureOption,
   247  ) *BootstrapProcedure {
   248  	bootstrapProcedure := &BootstrapProcedure{
   249  		BootstrapParams: BootstrapParams{
   250  			accountKeys: BootstrapAccountKeys{
   251  				ServiceAccountPublicKeys:       []flow.AccountPublicKey{serviceAccountPublicKey},
   252  				FungibleTokenAccountPublicKeys: []flow.AccountPublicKey{serviceAccountPublicKey},
   253  				FlowTokenAccountPublicKeys:     []flow.AccountPublicKey{serviceAccountPublicKey},
   254  				NodeAccountPublicKeys:          []flow.AccountPublicKey{serviceAccountPublicKey},
   255  			},
   256  			transactionFees:     BootstrapProcedureFeeParameters{0, 0, 0},
   257  			epochConfig:         epochs.DefaultEpochConfig(),
   258  			versionFreezePeriod: DefaultVersionFreezePeriod,
   259  		},
   260  	}
   261  
   262  	for _, applyOption := range opts {
   263  		bootstrapProcedure = applyOption(bootstrapProcedure)
   264  	}
   265  	return bootstrapProcedure
   266  }
   267  
   268  func (b *BootstrapProcedure) NewExecutor(
   269  	ctx Context,
   270  	txnState storage.TransactionPreparer,
   271  ) ProcedureExecutor {
   272  	return newBootstrapExecutor(b.BootstrapParams, ctx, txnState)
   273  }
   274  
   275  func (proc *BootstrapProcedure) ComputationLimit(_ Context) uint64 {
   276  	return math.MaxUint64
   277  }
   278  
   279  func (proc *BootstrapProcedure) MemoryLimit(_ Context) uint64 {
   280  	return math.MaxUint64
   281  }
   282  
   283  func (proc *BootstrapProcedure) ShouldDisableMemoryAndInteractionLimits(_ Context) bool {
   284  	return true
   285  }
   286  
   287  func (BootstrapProcedure) Type() ProcedureType {
   288  	return BootstrapProcedureType
   289  }
   290  
   291  func (proc *BootstrapProcedure) ExecutionTime() logical.Time {
   292  	return 0
   293  }
   294  
   295  type bootstrapExecutor struct {
   296  	BootstrapParams
   297  
   298  	ctx      Context
   299  	txnState storage.TransactionPreparer
   300  
   301  	accountCreator environment.BootstrapAccountCreator
   302  }
   303  
   304  func newBootstrapExecutor(
   305  	params BootstrapParams,
   306  	ctx Context,
   307  	txnState storage.TransactionPreparer,
   308  ) *bootstrapExecutor {
   309  	return &bootstrapExecutor{
   310  		BootstrapParams: params,
   311  		ctx: NewContextFromParent(
   312  			ctx,
   313  			WithContractDeploymentRestricted(false)),
   314  		txnState: txnState,
   315  	}
   316  }
   317  
   318  func (b *bootstrapExecutor) Cleanup() {
   319  	// Do nothing.
   320  }
   321  
   322  func (b *bootstrapExecutor) Output() ProcedureOutput {
   323  	return ProcedureOutput{}
   324  }
   325  
   326  func (b *bootstrapExecutor) Preprocess() error {
   327  	// Do nothing.
   328  	return nil
   329  }
   330  
   331  func (b *bootstrapExecutor) Execute() error {
   332  	b.rootBlock = flow.Genesis(flow.ChainID(b.ctx.Chain.String())).Header
   333  
   334  	// initialize the account addressing state
   335  	b.accountCreator = environment.NewBootstrapAccountCreator(
   336  		b.txnState,
   337  		b.ctx.Chain,
   338  		environment.NewAccounts(b.txnState))
   339  
   340  	service := b.createServiceAccount()
   341  
   342  	fungibleToken := b.deployFungibleToken()
   343  	nonFungibleToken := b.deployNonFungibleToken(service)
   344  	b.deployMetadataViews(fungibleToken, nonFungibleToken)
   345  	flowToken := b.deployFlowToken(service, fungibleToken, nonFungibleToken)
   346  	storageFees := b.deployStorageFees(service, fungibleToken, flowToken)
   347  	feeContract := b.deployFlowFees(service, fungibleToken, flowToken, storageFees)
   348  
   349  	if b.initialTokenSupply > 0 {
   350  		b.mintInitialTokens(service, fungibleToken, flowToken, b.initialTokenSupply)
   351  	}
   352  
   353  	b.deployServiceAccount(service, fungibleToken, flowToken, feeContract)
   354  
   355  	b.setupParameters(
   356  		service,
   357  		b.accountCreationFee,
   358  		b.minimumStorageReservation,
   359  		b.storagePerFlow,
   360  		b.restrictedAccountCreationEnabled,
   361  	)
   362  
   363  	b.setupFees(
   364  		service,
   365  		feeContract,
   366  		b.transactionFees.SurgeFactor,
   367  		b.transactionFees.InclusionEffortCost,
   368  		b.transactionFees.ExecutionEffortCost,
   369  	)
   370  
   371  	b.setContractDeploymentRestrictions(service, b.restrictedContractDeployment)
   372  
   373  	b.setupExecutionWeights(service)
   374  
   375  	b.setupStorageForServiceAccounts(service, fungibleToken, flowToken, feeContract)
   376  
   377  	b.createMinter(service, flowToken)
   378  
   379  	b.deployDKG(service)
   380  
   381  	b.deployQC(service)
   382  
   383  	b.deployIDTableStaking(service, fungibleToken, flowToken, feeContract)
   384  
   385  	b.deployEpoch(service, fungibleToken, flowToken, feeContract)
   386  
   387  	b.deployVersionBeacon(service, b.versionFreezePeriod)
   388  
   389  	b.deployRandomBeaconHistory(service)
   390  
   391  	// deploy staking proxy contract to the service account
   392  	b.deployStakingProxyContract(service)
   393  
   394  	// deploy locked tokens contract to the service account
   395  	b.deployLockedTokensContract(service, fungibleToken, flowToken)
   396  
   397  	// deploy staking collection contract to the service account
   398  	b.deployStakingCollection(service, fungibleToken, flowToken)
   399  
   400  	b.registerNodes(service, fungibleToken, flowToken)
   401  
   402  	// set the list of nodes which are allowed to stake in this network
   403  	b.setStakingAllowlist(service, b.identities.NodeIDs())
   404  
   405  	// sets up the EVM environment
   406  	b.setupEVM(service, fungibleToken, flowToken)
   407  
   408  	return nil
   409  }
   410  
   411  func (b *bootstrapExecutor) createAccount(publicKeys []flow.AccountPublicKey) flow.Address {
   412  	address, err := b.accountCreator.CreateBootstrapAccount(publicKeys)
   413  	if err != nil {
   414  		panic(fmt.Sprintf("failed to create account: %s", err))
   415  	}
   416  
   417  	return address
   418  }
   419  
   420  func (b *bootstrapExecutor) createServiceAccount() flow.Address {
   421  	address, err := b.accountCreator.CreateBootstrapAccount(
   422  		b.accountKeys.ServiceAccountPublicKeys)
   423  	if err != nil {
   424  		panic(fmt.Sprintf("failed to create service account: %s", err))
   425  	}
   426  
   427  	return address
   428  }
   429  
   430  func (b *bootstrapExecutor) deployFungibleToken() flow.Address {
   431  	fungibleToken := b.createAccount(b.accountKeys.FungibleTokenAccountPublicKeys)
   432  
   433  	txError, err := b.invokeMetaTransaction(
   434  		b.ctx,
   435  		Transaction(
   436  			blueprints.DeployFungibleTokenContractTransaction(fungibleToken),
   437  			0),
   438  	)
   439  	panicOnMetaInvokeErrf("failed to deploy fungible token contract: %s", txError, err)
   440  	return fungibleToken
   441  }
   442  
   443  func (b *bootstrapExecutor) deployNonFungibleToken(deployTo flow.Address) flow.Address {
   444  
   445  	txError, err := b.invokeMetaTransaction(
   446  		b.ctx,
   447  		Transaction(
   448  			blueprints.DeployNonFungibleTokenContractTransaction(deployTo),
   449  			0),
   450  	)
   451  	panicOnMetaInvokeErrf("failed to deploy non-fungible token contract: %s", txError, err)
   452  	return deployTo
   453  }
   454  
   455  func (b *bootstrapExecutor) deployMetadataViews(fungibleToken, nonFungibleToken flow.Address) {
   456  
   457  	txError, err := b.invokeMetaTransaction(
   458  		b.ctx,
   459  		Transaction(
   460  			blueprints.DeployMetadataViewsContractTransaction(fungibleToken, nonFungibleToken),
   461  			0),
   462  	)
   463  	panicOnMetaInvokeErrf("failed to deploy metadata views contract: %s", txError, err)
   464  
   465  	txError, err = b.invokeMetaTransaction(
   466  		b.ctx,
   467  		Transaction(
   468  			blueprints.DeployViewResolverContractTransaction(nonFungibleToken),
   469  			0),
   470  	)
   471  	panicOnMetaInvokeErrf("failed to deploy view resolver contract: %s", txError, err)
   472  
   473  	txError, err = b.invokeMetaTransaction(
   474  		b.ctx,
   475  		Transaction(
   476  			blueprints.DeployFungibleTokenMetadataViewsContractTransaction(fungibleToken, nonFungibleToken),
   477  			0),
   478  	)
   479  	panicOnMetaInvokeErrf("failed to deploy fungible token metadata views contract: %s", txError, err)
   480  }
   481  
   482  func (b *bootstrapExecutor) deployFlowToken(service, fungibleToken, metadataViews flow.Address) flow.Address {
   483  	flowToken := b.createAccount(b.accountKeys.FlowTokenAccountPublicKeys)
   484  	txError, err := b.invokeMetaTransaction(
   485  		b.ctx,
   486  		Transaction(
   487  			blueprints.DeployFlowTokenContractTransaction(
   488  				service,
   489  				fungibleToken,
   490  				metadataViews,
   491  				flowToken),
   492  			0),
   493  	)
   494  	panicOnMetaInvokeErrf("failed to deploy Flow token contract: %s", txError, err)
   495  	return flowToken
   496  }
   497  
   498  func (b *bootstrapExecutor) deployFlowFees(service, fungibleToken, flowToken, storageFees flow.Address) flow.Address {
   499  	flowFees := b.createAccount(b.accountKeys.FlowFeesAccountPublicKeys)
   500  
   501  	txError, err := b.invokeMetaTransaction(
   502  		b.ctx,
   503  		Transaction(
   504  			blueprints.DeployTxFeesContractTransaction(
   505  				service,
   506  				fungibleToken,
   507  				flowToken,
   508  				storageFees,
   509  				flowFees,
   510  			),
   511  			0),
   512  	)
   513  	panicOnMetaInvokeErrf("failed to deploy fees contract: %s", txError, err)
   514  	return flowFees
   515  }
   516  
   517  func (b *bootstrapExecutor) deployStorageFees(service, fungibleToken, flowToken flow.Address) flow.Address {
   518  	contract := contracts.FlowStorageFees(
   519  		fungibleToken.HexWithPrefix(),
   520  		flowToken.HexWithPrefix(),
   521  	)
   522  
   523  	// deploy storage fees contract on the service account
   524  	txError, err := b.invokeMetaTransaction(
   525  		b.ctx,
   526  		Transaction(
   527  			blueprints.DeployStorageFeesContractTransaction(
   528  				service,
   529  				contract),
   530  			0),
   531  	)
   532  	panicOnMetaInvokeErrf("failed to deploy storage fees contract: %s", txError, err)
   533  	return service
   534  }
   535  
   536  func (b *bootstrapExecutor) createMinter(service, flowToken flow.Address) {
   537  	txError, err := b.invokeMetaTransaction(
   538  		b.ctx,
   539  		Transaction(
   540  			blueprints.CreateFlowTokenMinterTransaction(
   541  				service,
   542  				flowToken),
   543  			0),
   544  	)
   545  	panicOnMetaInvokeErrf("failed to create flow token minter: %s", txError, err)
   546  }
   547  
   548  func (b *bootstrapExecutor) deployDKG(service flow.Address) {
   549  	contract := contracts.FlowDKG()
   550  	txError, err := b.invokeMetaTransaction(
   551  		b.ctx,
   552  		Transaction(
   553  			blueprints.DeployContractTransaction(service, contract, "FlowDKG"),
   554  			0,
   555  		),
   556  	)
   557  	panicOnMetaInvokeErrf("failed to deploy DKG contract: %s", txError, err)
   558  }
   559  
   560  func (b *bootstrapExecutor) deployQC(service flow.Address) {
   561  	contract := contracts.FlowQC()
   562  	txError, err := b.invokeMetaTransaction(
   563  		b.ctx,
   564  		Transaction(
   565  			blueprints.DeployContractTransaction(service, contract, "FlowClusterQC"),
   566  			0,
   567  		),
   568  	)
   569  	panicOnMetaInvokeErrf("failed to deploy QC contract: %s", txError, err)
   570  }
   571  
   572  func (b *bootstrapExecutor) deployIDTableStaking(service, fungibleToken, flowToken, flowFees flow.Address) {
   573  
   574  	contract := contracts.FlowIDTableStaking(
   575  		fungibleToken.HexWithPrefix(),
   576  		flowToken.HexWithPrefix(),
   577  		flowFees.HexWithPrefix(),
   578  		true)
   579  
   580  	txError, err := b.invokeMetaTransaction(
   581  		b.ctx,
   582  		Transaction(
   583  			blueprints.DeployIDTableStakingTransaction(service,
   584  				contract,
   585  				b.epochConfig.EpochTokenPayout,
   586  				b.epochConfig.RewardCut),
   587  			0,
   588  		),
   589  	)
   590  	panicOnMetaInvokeErrf("failed to deploy IDTableStaking contract: %s", txError, err)
   591  }
   592  
   593  func (b *bootstrapExecutor) deployEpoch(service, fungibleToken, flowToken, flowFees flow.Address) {
   594  
   595  	contract := contracts.FlowEpoch(
   596  		fungibleToken.HexWithPrefix(),
   597  		flowToken.HexWithPrefix(),
   598  		service.HexWithPrefix(),
   599  		service.HexWithPrefix(),
   600  		service.HexWithPrefix(),
   601  		flowFees.HexWithPrefix(),
   602  	)
   603  
   604  	context := NewContextFromParent(b.ctx,
   605  		WithBlockHeader(b.rootBlock),
   606  		WithBlocks(&environment.NoopBlockFinder{}),
   607  	)
   608  
   609  	txError, err := b.invokeMetaTransaction(
   610  		context,
   611  		Transaction(
   612  			blueprints.DeployEpochTransaction(service, contract, b.epochConfig),
   613  			0,
   614  		),
   615  	)
   616  	panicOnMetaInvokeErrf("failed to deploy Epoch contract: %s", txError, err)
   617  }
   618  
   619  func (b *bootstrapExecutor) deployServiceAccount(service, fungibleToken, flowToken, feeContract flow.Address) {
   620  	contract := contracts.FlowServiceAccount(
   621  		fungibleToken.HexWithPrefix(),
   622  		flowToken.HexWithPrefix(),
   623  		feeContract.HexWithPrefix(),
   624  		service.HexWithPrefix(),
   625  	)
   626  
   627  	txError, err := b.invokeMetaTransaction(
   628  		b.ctx,
   629  		Transaction(
   630  			blueprints.DeployContractTransaction(
   631  				service,
   632  				contract,
   633  				"FlowServiceAccount"),
   634  			0),
   635  	)
   636  	panicOnMetaInvokeErrf("failed to deploy service account contract: %s", txError, err)
   637  }
   638  
   639  func (b *bootstrapExecutor) mintInitialTokens(
   640  	service, fungibleToken, flowToken flow.Address,
   641  	initialSupply cadence.UFix64,
   642  ) {
   643  	txError, err := b.invokeMetaTransaction(
   644  		b.ctx,
   645  		Transaction(
   646  			blueprints.MintFlowTokenTransaction(
   647  				fungibleToken,
   648  				flowToken,
   649  				service,
   650  				initialSupply),
   651  			0),
   652  	)
   653  	panicOnMetaInvokeErrf("failed to mint initial token supply: %s", txError, err)
   654  }
   655  
   656  func (b *bootstrapExecutor) setupParameters(
   657  	service flow.Address,
   658  	addressCreationFee,
   659  	minimumStorageReservation,
   660  	storagePerFlow cadence.UFix64,
   661  	restrictedAccountCreationEnabled cadence.Bool,
   662  ) {
   663  	txError, err := b.invokeMetaTransaction(
   664  		b.ctx,
   665  		Transaction(
   666  			blueprints.SetupParametersTransaction(
   667  				service,
   668  				addressCreationFee,
   669  				minimumStorageReservation,
   670  				storagePerFlow,
   671  				restrictedAccountCreationEnabled,
   672  			),
   673  			0),
   674  	)
   675  	panicOnMetaInvokeErrf("failed to setup parameters: %s", txError, err)
   676  }
   677  
   678  func (b *bootstrapExecutor) setupFees(
   679  	service, flowFees flow.Address,
   680  	surgeFactor, inclusionEffortCost, executionEffortCost cadence.UFix64,
   681  ) {
   682  	txError, err := b.invokeMetaTransaction(
   683  		b.ctx,
   684  		Transaction(
   685  			blueprints.SetupFeesTransaction(
   686  				service,
   687  				flowFees,
   688  				surgeFactor,
   689  				inclusionEffortCost,
   690  				executionEffortCost,
   691  			),
   692  			0),
   693  	)
   694  	panicOnMetaInvokeErrf("failed to setup fees: %s", txError, err)
   695  }
   696  
   697  func (b *bootstrapExecutor) setupExecutionWeights(service flow.Address) {
   698  	// if executionEffortWeights were not set skip this part and just use the defaults.
   699  	if b.executionEffortWeights != nil {
   700  		b.setupExecutionEffortWeights(service)
   701  	}
   702  	// if executionMemoryWeights were not set skip this part and just use the defaults.
   703  	if b.executionMemoryWeights != nil {
   704  		b.setupExecutionMemoryWeights(service)
   705  	}
   706  	if b.executionMemoryLimit != 0 {
   707  		b.setExecutionMemoryLimitTransaction(service)
   708  	}
   709  }
   710  
   711  func (b *bootstrapExecutor) setupExecutionEffortWeights(service flow.Address) {
   712  	weights := b.executionEffortWeights
   713  
   714  	uintWeights := make(map[uint]uint64, len(weights))
   715  	for i, weight := range weights {
   716  		uintWeights[uint(i)] = weight
   717  	}
   718  
   719  	tb, err := blueprints.SetExecutionEffortWeightsTransaction(service, uintWeights)
   720  	if err != nil {
   721  		panic(fmt.Sprintf("failed to setup execution effort weights %s", err.Error()))
   722  	}
   723  
   724  	txError, err := b.invokeMetaTransaction(
   725  		b.ctx,
   726  		Transaction(
   727  			tb,
   728  			0),
   729  	)
   730  	panicOnMetaInvokeErrf("failed to setup execution effort weights: %s", txError, err)
   731  }
   732  
   733  func (b *bootstrapExecutor) setupExecutionMemoryWeights(service flow.Address) {
   734  	weights := b.executionMemoryWeights
   735  
   736  	uintWeights := make(map[uint]uint64, len(weights))
   737  	for i, weight := range weights {
   738  		uintWeights[uint(i)] = weight
   739  	}
   740  
   741  	tb, err := blueprints.SetExecutionMemoryWeightsTransaction(service, uintWeights)
   742  	if err != nil {
   743  		panic(fmt.Sprintf("failed to setup execution memory weights %s", err.Error()))
   744  	}
   745  
   746  	txError, err := b.invokeMetaTransaction(
   747  		b.ctx,
   748  		Transaction(
   749  			tb,
   750  			0),
   751  	)
   752  	panicOnMetaInvokeErrf("failed to setup execution memory weights: %s", txError, err)
   753  }
   754  
   755  func (b *bootstrapExecutor) setExecutionMemoryLimitTransaction(service flow.Address) {
   756  
   757  	tb, err := blueprints.SetExecutionMemoryLimitTransaction(service, b.executionMemoryLimit)
   758  	if err != nil {
   759  		panic(fmt.Sprintf("failed to setup execution memory limit %s", err.Error()))
   760  	}
   761  
   762  	txError, err := b.invokeMetaTransaction(
   763  		b.ctx,
   764  		Transaction(
   765  			tb,
   766  			0),
   767  	)
   768  	panicOnMetaInvokeErrf("failed to setup execution memory limit: %s", txError, err)
   769  }
   770  
   771  func (b *bootstrapExecutor) setupStorageForServiceAccounts(
   772  	service, fungibleToken, flowToken, feeContract flow.Address,
   773  ) {
   774  	txError, err := b.invokeMetaTransaction(
   775  		b.ctx,
   776  		Transaction(
   777  			blueprints.SetupStorageForServiceAccountsTransaction(
   778  				service,
   779  				fungibleToken,
   780  				flowToken,
   781  				feeContract),
   782  			0),
   783  	)
   784  	panicOnMetaInvokeErrf("failed to setup storage for service accounts: %s", txError, err)
   785  }
   786  
   787  func (b *bootstrapExecutor) setupStorageForAccount(
   788  	account, service, fungibleToken, flowToken flow.Address,
   789  ) {
   790  	txError, err := b.invokeMetaTransaction(
   791  		b.ctx,
   792  		Transaction(
   793  			blueprints.SetupStorageForAccountTransaction(
   794  				account,
   795  				service,
   796  				fungibleToken,
   797  				flowToken),
   798  			0),
   799  	)
   800  	panicOnMetaInvokeErrf("failed to setup storage for service accounts: %s", txError, err)
   801  }
   802  
   803  func (b *bootstrapExecutor) setStakingAllowlist(
   804  	service flow.Address,
   805  	allowedIDs []flow.Identifier,
   806  ) {
   807  
   808  	txError, err := b.invokeMetaTransaction(
   809  		b.ctx,
   810  		Transaction(
   811  			blueprints.SetStakingAllowlistTransaction(
   812  				service,
   813  				allowedIDs,
   814  			),
   815  			0),
   816  	)
   817  	panicOnMetaInvokeErrf("failed to set staking allow-list: %s", txError, err)
   818  }
   819  
   820  func (b *bootstrapExecutor) setupEVM(serviceAddress, fungibleTokenAddress, flowTokenAddress flow.Address) {
   821  	if b.setupEVMEnabled {
   822  		// account for storage
   823  		// we dont need to deploy anything to this account, but it needs to exist
   824  		// so that we can store the EVM state on it
   825  		evmAcc := b.createAccount(nil)
   826  		b.setupStorageForAccount(evmAcc, serviceAddress, fungibleTokenAddress, flowTokenAddress)
   827  
   828  		// deploy the EVM contract to the service account
   829  		tx := blueprints.DeployContractTransaction(
   830  			serviceAddress,
   831  			stdlib.ContractCode(flowTokenAddress, bool(b.evmAbiOnly)),
   832  			stdlib.ContractName,
   833  		)
   834  		// WithEVMEnabled should only be used after we create an account for storage
   835  		txError, err := b.invokeMetaTransaction(
   836  			NewContextFromParent(b.ctx, WithEVMEnabled(true)),
   837  			Transaction(tx, 0),
   838  		)
   839  		panicOnMetaInvokeErrf("failed to deploy EVM contract: %s", txError, err)
   840  	}
   841  }
   842  
   843  func (b *bootstrapExecutor) registerNodes(service, fungibleToken, flowToken flow.Address) {
   844  	for _, id := range b.identities {
   845  
   846  		// create a staking account for the node
   847  		nodeAddress := b.createAccount(b.accountKeys.NodeAccountPublicKeys)
   848  
   849  		// give a vault resource to the staking account
   850  		txError, err := b.invokeMetaTransaction(
   851  			b.ctx,
   852  			Transaction(
   853  				blueprints.SetupAccountTransaction(fungibleToken,
   854  					flowToken,
   855  					nodeAddress),
   856  				0,
   857  			),
   858  		)
   859  		panicOnMetaInvokeErrf("failed to setup machine account: %s", txError, err)
   860  
   861  		// fund the staking account
   862  		txError, err = b.invokeMetaTransaction(
   863  			b.ctx,
   864  			Transaction(blueprints.FundAccountTransaction(service,
   865  				fungibleToken,
   866  				flowToken,
   867  				nodeAddress),
   868  				0),
   869  		)
   870  		panicOnMetaInvokeErrf("failed to fund node staking account: %s", txError, err)
   871  
   872  		// register the node
   873  		// for collection/consensus nodes this will also create the machine account
   874  		// and set it up with the QC/DKG participant resource
   875  		txError, err = b.invokeMetaTransaction(
   876  			b.ctx,
   877  			Transaction(blueprints.RegisterNodeTransaction(service,
   878  				flowToken,
   879  				nodeAddress,
   880  				id),
   881  				0),
   882  		)
   883  		panicOnMetaInvokeErrf("failed to register node: %s", txError, err)
   884  	}
   885  }
   886  
   887  func (b *bootstrapExecutor) deployStakingProxyContract(service flow.Address) {
   888  	contract := contracts.FlowStakingProxy()
   889  	txError, err := b.invokeMetaTransaction(
   890  		b.ctx,
   891  		Transaction(
   892  			blueprints.DeployContractTransaction(service, contract, "StakingProxy"),
   893  			0,
   894  		),
   895  	)
   896  	panicOnMetaInvokeErrf("failed to deploy StakingProxy contract: %s", txError, err)
   897  }
   898  
   899  func (b *bootstrapExecutor) deployVersionBeacon(
   900  	service flow.Address,
   901  	versionFreezePeriod cadence.UInt64,
   902  ) {
   903  	tx := blueprints.DeployNodeVersionBeaconTransaction(service, versionFreezePeriod)
   904  	txError, err := b.invokeMetaTransaction(
   905  		b.ctx,
   906  		Transaction(
   907  			tx,
   908  			0,
   909  		),
   910  	)
   911  	panicOnMetaInvokeErrf("failed to deploy NodeVersionBeacon contract: %s", txError, err)
   912  }
   913  
   914  func (b *bootstrapExecutor) deployRandomBeaconHistory(
   915  	service flow.Address,
   916  ) {
   917  	tx := blueprints.DeployRandomBeaconHistoryTransaction(service)
   918  	txError, err := b.invokeMetaTransaction(
   919  		b.ctx,
   920  		Transaction(
   921  			tx,
   922  			0,
   923  		),
   924  	)
   925  	panicOnMetaInvokeErrf("failed to deploy RandomBeaconHistory history contract: %s", txError, err)
   926  }
   927  
   928  func (b *bootstrapExecutor) deployLockedTokensContract(
   929  	service flow.Address, fungibleTokenAddress,
   930  	flowTokenAddress flow.Address,
   931  ) {
   932  
   933  	publicKeys, err := flow.EncodeRuntimeAccountPublicKeys(b.accountKeys.ServiceAccountPublicKeys)
   934  	if err != nil {
   935  		panic(err)
   936  	}
   937  
   938  	contract := contracts.FlowLockedTokens(
   939  		fungibleTokenAddress.Hex(),
   940  		flowTokenAddress.Hex(),
   941  		service.Hex(),
   942  		service.Hex(),
   943  		service.Hex())
   944  
   945  	txError, err := b.invokeMetaTransaction(
   946  		b.ctx,
   947  		Transaction(
   948  			blueprints.DeployLockedTokensTransaction(service, contract, publicKeys),
   949  			0,
   950  		),
   951  	)
   952  
   953  	panicOnMetaInvokeErrf("failed to deploy LockedTokens contract: %s", txError, err)
   954  }
   955  
   956  func (b *bootstrapExecutor) deployStakingCollection(
   957  	service flow.Address,
   958  	fungibleTokenAddress, flowTokenAddress flow.Address,
   959  ) {
   960  	contract := contracts.FlowStakingCollection(
   961  		fungibleTokenAddress.Hex(),
   962  		flowTokenAddress.Hex(),
   963  		service.Hex(),
   964  		service.Hex(),
   965  		service.Hex(),
   966  		service.Hex(),
   967  		service.Hex(),
   968  		service.Hex(),
   969  		service.Hex())
   970  	txError, err := b.invokeMetaTransaction(
   971  		b.ctx,
   972  		Transaction(
   973  			blueprints.DeployContractTransaction(service, contract, "FlowStakingCollection"),
   974  			0,
   975  		),
   976  	)
   977  	panicOnMetaInvokeErrf("failed to deploy FlowStakingCollection contract: %s", txError, err)
   978  }
   979  
   980  func (b *bootstrapExecutor) setContractDeploymentRestrictions(
   981  	service flow.Address,
   982  	deployment *bool,
   983  ) {
   984  	if deployment == nil {
   985  		return
   986  	}
   987  
   988  	txBody, err := blueprints.SetIsContractDeploymentRestrictedTransaction(service, *deployment)
   989  	if err != nil {
   990  		panic(err)
   991  	}
   992  	txError, err := b.invokeMetaTransaction(
   993  		b.ctx,
   994  		Transaction(
   995  			txBody,
   996  			0,
   997  		),
   998  	)
   999  	panicOnMetaInvokeErrf("failed to deploy FlowStakingCollection contract: %s", txError, err)
  1000  }
  1001  
  1002  func panicOnMetaInvokeErrf(msg string, txError errors.CodedError, err error) {
  1003  	if txError != nil {
  1004  		panic(fmt.Sprintf(msg, txError.Error()))
  1005  	}
  1006  	if err != nil {
  1007  		panic(fmt.Sprintf(msg, err.Error()))
  1008  	}
  1009  }
  1010  
  1011  // invokeMetaTransaction invokes a meta transaction inside the context of an
  1012  // outer transaction.
  1013  //
  1014  // Errors that occur in a meta transaction are propagated as a single error
  1015  // that can be captured by the Cadence runtime and eventually disambiguated by
  1016  // the parent context.
  1017  func (b *bootstrapExecutor) invokeMetaTransaction(
  1018  	parentCtx Context,
  1019  	tx *TransactionProcedure,
  1020  ) (
  1021  	errors.CodedError,
  1022  	error,
  1023  ) {
  1024  	// do not deduct fees or check storage in meta transactions
  1025  	ctx := NewContextFromParent(parentCtx,
  1026  		WithAccountStorageLimit(false),
  1027  		WithTransactionFeesEnabled(false),
  1028  		WithAuthorizationChecksEnabled(false),
  1029  		WithSequenceNumberCheckAndIncrementEnabled(false),
  1030  
  1031  		// disable interaction and computation limits for bootstrapping
  1032  		WithMemoryAndInteractionLimitsDisabled(),
  1033  		WithComputationLimit(math.MaxUint64),
  1034  	)
  1035  
  1036  	executor := tx.NewExecutor(ctx, b.txnState)
  1037  	err := Run(executor)
  1038  
  1039  	return executor.Output().Err, err
  1040  }