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 }