diff --git a/cmd/bootstrap/utils/key_generation.go b/cmd/bootstrap/utils/key_generation.go index 1857bf34eee..627030a789f 100644 --- a/cmd/bootstrap/utils/key_generation.go +++ b/cmd/bootstrap/utils/key_generation.go @@ -13,6 +13,7 @@ import ( sdk "github.com/onflow/flow-go-sdk" sdkcrypto "github.com/onflow/flow-go-sdk/crypto" + "github.com/onflow/flow-go/fvm/systemcontracts" "github.com/onflow/flow-go/model/bootstrap" "github.com/onflow/flow-go/model/encodable" "github.com/onflow/flow-go/model/flow" @@ -173,7 +174,7 @@ func WriteMachineAccountFiles(chainID flow.ChainID, nodeInfos []bootstrap.NodeIn // // for the machine account key, we keep track of the address index to map // the Flow address of the machine account to the key. - addressIndex := uint64(4) + addressIndex := uint64(systemcontracts.LastSystemAccountIndex) for _, nodeInfo := range nodeInfos { // retrieve private representation of the node diff --git a/cmd/bootstrap/utils/key_generation_test.go b/cmd/bootstrap/utils/key_generation_test.go index d4ea3e1e59f..a261c07238d 100644 --- a/cmd/bootstrap/utils/key_generation_test.go +++ b/cmd/bootstrap/utils/key_generation_test.go @@ -10,6 +10,7 @@ import ( sdkcrypto "github.com/onflow/flow-go-sdk/crypto" + "github.com/onflow/flow-go/fvm/systemcontracts" "github.com/onflow/flow-go/model/bootstrap" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/utils/unittest" @@ -62,7 +63,7 @@ func TestWriteMachineAccountFiles(t *testing.T) { expected := make(map[string]bootstrap.NodeMachineAccountInfo) for i, node := range nodes { // See comments in WriteMachineAccountFiles for why addresses take this form - addr, err := chain.AddressAtIndex(uint64(6 + i*2)) + addr, err := chain.AddressAtIndex(uint64(systemcontracts.LastSystemAccountIndex + (i+1)*2)) require.NoError(t, err) private, err := node.Private() require.NoError(t, err) diff --git a/cmd/util/ledger/reporters/fungible_token_tracker_test.go b/cmd/util/ledger/reporters/fungible_token_tracker_test.go index a752f2cbaa7..d5b8879bb36 100644 --- a/cmd/util/ledger/reporters/fungible_token_tracker_test.go +++ b/cmd/util/ledger/reporters/fungible_token_tracker_test.go @@ -166,10 +166,11 @@ func TestFungibleTokenTracker(t *testing.T) { // wrappedToken require.True(t, strings.Contains(string(data), `{"path":"storage/wrappedToken/vault","address":"8c5303eaa26202d6","balance":105,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) // flowTokenVaults - require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"8c5303eaa26202d6","balance":99999999999699895,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) + require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"8c5303eaa26202d6","balance":99999999999599895,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"9a0766d93b6608b7","balance":100000,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"7e60df042a9c0868","balance":100000,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"912d5440f7e3769e","balance":100000,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) + require.True(t, strings.Contains(string(data), `{"path":"storage/flowTokenVault","address":"754aed9de6197641","balance":100000,"type_id":"A.7e60df042a9c0868.FlowToken.Vault"}`)) // do not remove this line, see https://github.com/onflow/flow-go/pull/2237 t.Log("success") diff --git a/engine/execution/computation/execution_verification_test.go b/engine/execution/computation/execution_verification_test.go index fe31105f2bb..2956ade0e86 100644 --- a/engine/execution/computation/execution_verification_test.go +++ b/engine/execution/computation/execution_verification_test.go @@ -194,7 +194,7 @@ func Test_ExecutionMatchesVerification(t *testing.T) { accountPrivKey, createAccountTx := testutil.CreateAccountCreationTransaction(t, chain) // this should return the address of newly created account - accountAddress, err := chain.AddressAtIndex(5) + accountAddress, err := chain.AddressAtIndex(systemcontracts.LastSystemAccountIndex + 1) require.NoError(t, err) err = testutil.SignTransactionAsServiceAccount(createAccountTx, 0, chain) @@ -236,7 +236,7 @@ func Test_ExecutionMatchesVerification(t *testing.T) { t.Run("with failed transaction fee deduction", func(t *testing.T) { accountPrivKey, createAccountTx := testutil.CreateAccountCreationTransaction(t, chain) // this should return the address of newly created account - accountAddress, err := chain.AddressAtIndex(5) + accountAddress, err := chain.AddressAtIndex(systemcontracts.LastSystemAccountIndex + 1) require.NoError(t, err) err = testutil.SignTransactionAsServiceAccount(createAccountTx, 0, chain) @@ -628,7 +628,7 @@ func TestTransactionFeeDeduction(t *testing.T) { privateKey, createAccountTx := testutil.CreateAccountCreationTransaction(t, chain) // this should return the address of newly created account - address, err := chain.AddressAtIndex(5) + address, err := chain.AddressAtIndex(systemcontracts.LastSystemAccountIndex + 1) require.NoError(t, err) err = testutil.SignTransactionAsServiceAccount(createAccountTx, 0, chain) diff --git a/engine/execution/state/bootstrap/bootstrap.go b/engine/execution/state/bootstrap/bootstrap.go index 324155458a4..97656092d09 100644 --- a/engine/execution/state/bootstrap/bootstrap.go +++ b/engine/execution/state/bootstrap/bootstrap.go @@ -51,8 +51,6 @@ func (b *Bootstrapper) BootstrapLedger( fvm.WithLogger(b.logger), fvm.WithMaxStateInteractionSize(ledgerIntractionLimitNeededForBootstrapping), fvm.WithChain(chain), - // TODO (JanezP): move this deeper - fvm.WithEVMEnabled(true), ) bootstrap := fvm.Bootstrap( diff --git a/engine/execution/state/bootstrap/bootstrap_test.go b/engine/execution/state/bootstrap/bootstrap_test.go index 82db49066e3..edc97efb700 100644 --- a/engine/execution/state/bootstrap/bootstrap_test.go +++ b/engine/execution/state/bootstrap/bootstrap_test.go @@ -53,7 +53,7 @@ func TestBootstrapLedger(t *testing.T) { } func TestBootstrapLedger_ZeroTokenSupply(t *testing.T) { - expectedStateCommitmentBytes, _ := hex.DecodeString("d1a6903c063bd07e1824e17f6d1a6e1b6d8bdf564ffb41b53062206dcc2bc670") + expectedStateCommitmentBytes, _ := hex.DecodeString("a76ef8608e869025232141334d4559900709b9ef59bfaee3393cc33b69f5483e") expectedStateCommitment, err := flow.ToStateCommitment(expectedStateCommitmentBytes) require.NoError(t, err) diff --git a/fvm/bootstrap.go b/fvm/bootstrap.go index 750f2d9d89a..1735d243e17 100644 --- a/fvm/bootstrap.go +++ b/fvm/bootstrap.go @@ -15,6 +15,7 @@ import ( "github.com/onflow/flow-go/fvm/meter" "github.com/onflow/flow-go/fvm/storage" "github.com/onflow/flow-go/fvm/storage/logical" + "github.com/onflow/flow-go/fvm/systemcontracts" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/epochs" ) @@ -257,6 +258,7 @@ func Bootstrap( transactionFees: BootstrapProcedureFeeParameters{0, 0, 0}, epochConfig: epochs.DefaultEpochConfig(), versionFreezePeriod: DefaultVersionFreezePeriod, + setupEVMEnabled: true, }, } @@ -340,8 +342,22 @@ func (b *bootstrapExecutor) Execute() error { b.ctx.Chain, environment.NewAccounts(b.txnState)) + expectAccounts := func(n uint64) error { + ag := environment.NewAddressGenerator(b.txnState, b.ctx.Chain) + currentAddresses := ag.AddressCount() + if currentAddresses != n { + return fmt.Errorf("expected %d accounts, got %d", n, currentAddresses) + } + return nil + } + service := b.createServiceAccount() + err := expectAccounts(1) + if err != nil { + return err + } + env := templates.Environment{ ServiceAccountAddress: service.String(), } @@ -349,15 +365,35 @@ func (b *bootstrapExecutor) Execute() error { b.deployViewResolver(service, &env) b.deployBurner(service, &env) + err = expectAccounts(1) + if err != nil { + return err + } + fungibleToken := b.deployFungibleToken(&env) + + err = expectAccounts(systemcontracts.FungibleTokenAccountIndex) + if err != nil { + return err + } + nonFungibleToken := b.deployNonFungibleToken(service, &env) b.deployMetadataViews(fungibleToken, nonFungibleToken, &env) b.deployFungibleTokenSwitchboard(fungibleToken, &env) flowToken := b.deployFlowToken(service, &env) + err = expectAccounts(systemcontracts.FlowTokenAccountIndex) + if err != nil { + return err + } + b.deployStorageFees(service, &env) feeContract := b.deployFlowFees(service, &env) + err = expectAccounts(systemcontracts.FlowFeesAccountIndex) + if err != nil { + return err + } if b.initialTokenSupply > 0 { b.mintInitialTokens(service, fungibleToken, flowToken, b.initialTokenSupply) @@ -410,14 +446,19 @@ func (b *bootstrapExecutor) Execute() error { // deploy staking collection contract to the service account b.deployStakingCollection(service, &env) + // sets up the EVM environment + b.setupEVM(service, fungibleToken, flowToken) + + err = expectAccounts(systemcontracts.EVMStorageAccountIndex) + if err != nil { + return err + } + b.registerNodes(service, fungibleToken, flowToken) // set the list of nodes which are allowed to stake in this network b.setStakingAllowlist(service, b.identities.NodeIDs()) - // sets up the EVM environment - b.setupEVM(service, fungibleToken, flowToken) - return nil } @@ -911,7 +952,8 @@ func (b *bootstrapExecutor) registerNodes(service, fungibleToken, flowToken flow // fund the staking account txError, err = b.invokeMetaTransaction( b.ctx, - Transaction(blueprints.FundAccountTransaction(service, + Transaction(blueprints.FundAccountTransaction( + service, fungibleToken, flowToken, nodeAddress), @@ -924,7 +966,8 @@ func (b *bootstrapExecutor) registerNodes(service, fungibleToken, flowToken flow // and set it up with the QC/DKG participant resource txError, err = b.invokeMetaTransaction( b.ctx, - Transaction(blueprints.RegisterNodeTransaction(service, + Transaction(blueprints.RegisterNodeTransaction( + service, flowToken, fungibleToken, nodeAddress, diff --git a/fvm/evm/evm_test.go b/fvm/evm/evm_test.go index 51c1b0a22b3..03fef6df625 100644 --- a/fvm/evm/evm_test.go +++ b/fvm/evm/evm_test.go @@ -474,7 +474,6 @@ func RunWithNewEnvironment( baseBootstrapOpts := []fvm.BootstrapProcedureOption{ fvm.WithInitialTokenSupply(unittest.GenesisTokenSupply), - fvm.WithSetupEVMEnabled(true), } executionSnapshot, _, err := vm.Run( diff --git a/fvm/fvm_bench_test.go b/fvm/fvm_bench_test.go index 084c9847c70..795dacbc836 100644 --- a/fvm/fvm_bench_test.go +++ b/fvm/fvm_bench_test.go @@ -203,7 +203,6 @@ func NewBasicBlockExecutor(tb testing.TB, chain flow.Chain, logger zerolog.Logge fvm.WithMinimumStorageReservation(fvm.DefaultMinimumStorageReservation), fvm.WithTransactionFee(fvm.DefaultTransactionFees), fvm.WithStorageMBPerFLOW(fvm.DefaultStorageMBPerFLOW), - fvm.WithSetupEVMEnabled(true), ) require.NoError(tb, err) @@ -425,7 +424,7 @@ func BenchmarkRuntimeTransaction(b *testing.B) { } sc := systemcontracts.SystemContractsForChain(chain.ChainID()) - testContractAddress, err := chain.AddressAtIndex(systemcontracts.EVMStorageAccountIndex + 1) + testContractAddress, err := chain.AddressAtIndex(systemcontracts.LastSystemAccountIndex + 1) require.NoError(b, err) benchTransaction := func( diff --git a/fvm/fvm_blockcontext_test.go b/fvm/fvm_blockcontext_test.go index cd84b1a0af3..42523c70bb6 100644 --- a/fvm/fvm_blockcontext_test.go +++ b/fvm/fvm_blockcontext_test.go @@ -951,9 +951,6 @@ func TestBlockContext_ExecuteTransaction_StorageLimit(t *testing.T) { fvm.WithAccountCreationFee(fvm.DefaultAccountCreationFee), fvm.WithMinimumStorageReservation(fvm.DefaultMinimumStorageReservation), fvm.WithStorageMBPerFLOW(fvm.DefaultStorageMBPerFLOW), - // The evm account has a storage exception, and if we don't bootstrap with evm, - // the first created account will have that address. - fvm.WithSetupEVMEnabled(true), } t.Run("Storing too much data fails", newVMTest().withBootstrapProcedureOptions(bootstrapOptions...). @@ -1641,7 +1638,7 @@ func TestBlockContext_GetAccount(t *testing.T) { addressGen := chain.NewAddressGenerator() // skip the addresses of 4 reserved accounts - for i := 0; i < 4; i++ { + for i := 0; i < systemcontracts.LastSystemAccountIndex; i++ { _, err := addressGen.NextAddress() require.NoError(t, err) } @@ -1820,7 +1817,9 @@ func TestBlockContext_ExecuteTransaction_CreateAccount_WithMonotonicAddresses(t address := flow.ConvertAddress( data.(cadence.Event).Fields[0].(cadence.Address)) - require.Equal(t, flow.HexToAddress("05"), address) + // convert LastSystemAccountIndex + 1 to a flow.Address + expected := flow.HexToAddress(fmt.Sprintf("0x%02x", systemcontracts.LastSystemAccountIndex+1)) + require.Equal(t, expected, address) } func TestBlockContext_ExecuteTransaction_FailingTransactions(t *testing.T) { @@ -1866,7 +1865,6 @@ func TestBlockContext_ExecuteTransaction_FailingTransactions(t *testing.T) { fvm.WithExecutionMemoryLimit(math.MaxUint64), // The evm account has a storage exception, and if we don't bootstrap with evm, // the first created account will have that address. - fvm.WithSetupEVMEnabled(true), ).run( func(t *testing.T, vm fvm.VM, chain flow.Chain, ctx fvm.Context, snapshotTree snapshot.SnapshotTree) { ctx.LimitAccountStorage = true // this test requires storage limits to be enforced diff --git a/fvm/fvm_test.go b/fvm/fvm_test.go index ea064ffe155..1edecfdcd46 100644 --- a/fvm/fvm_test.go +++ b/fvm/fvm_test.go @@ -2726,7 +2726,6 @@ func TestTransientNetworkCoreContractAddresses(t *testing.T) { func TestEVM(t *testing.T) { t.Run("successful transaction", newVMTest(). - withBootstrapProcedureOptions(fvm.WithSetupEVMEnabled(true)). withContextOptions( fvm.WithEVMEnabled(true), fvm.WithCadenceLogging(true), @@ -2787,7 +2786,6 @@ func TestEVM(t *testing.T) { // available through the EVM contract, when bootstraped with `WithEVMABIOnly` t.Run("with ABI only EVM", newVMTest(). withBootstrapProcedureOptions( - fvm.WithSetupEVMEnabled(true), fvm.WithEVMABIOnly(true), ). withContextOptions( @@ -2838,7 +2836,6 @@ func TestEVM(t *testing.T) { // this test makes sure the execution error is correctly handled and returned as a correct type t.Run("execution reverted", newVMTest(). - withBootstrapProcedureOptions(fvm.WithSetupEVMEnabled(true)). withContextOptions( fvm.WithChain(flow.Emulator.Chain()), fvm.WithEVMEnabled(true), @@ -2879,7 +2876,6 @@ func TestEVM(t *testing.T) { // this test makes sure the EVM error is correctly returned as an error and has a correct type // we have implemented a snapshot wrapper to return an error from the EVM t.Run("internal evm error handling", newVMTest(). - withBootstrapProcedureOptions(fvm.WithSetupEVMEnabled(true)). withContextOptions( fvm.WithChain(flow.Emulator.Chain()), fvm.WithEVMEnabled(true), @@ -2937,9 +2933,6 @@ func TestEVM(t *testing.T) { ) t.Run("deploy contract code", newVMTest(). - withBootstrapProcedureOptions( - fvm.WithSetupEVMEnabled(true), - ). withContextOptions( // default is testnet, but testnet has a special EVM storage contract location // so we have to use emulator here so that the EVM storage contract is deployed diff --git a/fvm/systemcontracts/system_contracts.go b/fvm/systemcontracts/system_contracts.go index 0d7fe21e594..3ac5fa46646 100644 --- a/fvm/systemcontracts/system_contracts.go +++ b/fvm/systemcontracts/system_contracts.go @@ -59,12 +59,18 @@ const ( ContractStorageFeesFunction_getAccountsCapacityForTransactionStorageCheck = "getAccountsCapacityForTransactionStorageCheck" ContractStorageFeesFunction_defaultTokenAvailableBalance = "defaultTokenAvailableBalance" - // Indexes of the system contracts that are deployed to an address at a specific index + // These are the account indexes of system contracts as deployed by the default bootstrapping. + // On long-running networks some of these contracts might have been deployed after bootstrapping, + // and therefore might not be at these indexes. FungibleTokenAccountIndex = 2 FlowTokenAccountIndex = 3 FlowFeesAccountIndex = 4 EVMStorageAccountIndex = 5 + + // LastSystemAccountIndex is the last index of a system accounts. + // Other addresses will be created after this one. + LastSystemAccountIndex = EVMStorageAccountIndex ) // Well-known addresses for system contracts on long-running networks. diff --git a/integration/benchmark/load/load_type_test.go b/integration/benchmark/load/load_type_test.go index 1517924a7e5..7b4e37384a1 100644 --- a/integration/benchmark/load/load_type_test.go +++ b/integration/benchmark/load/load_type_test.go @@ -137,7 +137,6 @@ func bootstrapVM(t *testing.T, chain flow.Chain) (*fvm.VirtualMachine, fvm.Conte fvm.WithMinimumStorageReservation(fvm.DefaultMinimumStorageReservation), fvm.WithTransactionFee(fvm.DefaultTransactionFees), fvm.WithStorageMBPerFLOW(fvm.DefaultStorageMBPerFLOW), - fvm.WithSetupEVMEnabled(true), } executionSnapshot, _, err := vm.Run( diff --git a/utils/unittest/execution_state.go b/utils/unittest/execution_state.go index e9452a6b6b6..10efd0eae2c 100644 --- a/utils/unittest/execution_state.go +++ b/utils/unittest/execution_state.go @@ -23,7 +23,7 @@ const ServiceAccountPrivateKeySignAlgo = crypto.ECDSAP256 const ServiceAccountPrivateKeyHashAlgo = hash.SHA2_256 // Pre-calculated state commitment with root account with the above private key -const GenesisStateCommitmentHex = "9289842133d059d88ce17cdae58d6a3c02435aff4e89496283c08014bee9ce14" +const GenesisStateCommitmentHex = "950eead8a731067405a0b56858e70af4b318d8154a2923e0001b4e239fbd0e56" var GenesisStateCommitment flow.StateCommitment @@ -87,10 +87,10 @@ func genesisCommitHexByChainID(chainID flow.ChainID) string { return GenesisStateCommitmentHex } if chainID == flow.Testnet { - return "5f423e02622a761a860b55c53ed64234d04972d72b65f925d62f55f4cbced039" + return "74c54a0d99a9cbdbb835778be1d1aff419664639cf4b3667c7584840a2ea351b" } if chainID == flow.Sandboxnet { return "e1c08b17f9e5896f03fe28dd37ca396c19b26628161506924fbf785834646ea1" } - return "24c062634edd1d4b2e8cc6fa3adfffd4d8123cb2283c6ce7627c7f9e6d7bdca8" + return "abd550ebb99650c66d7a27c0a7ca08ab49fbdd5c618666f2bc026223030a12af" }