github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/cmd/util/ledger/migrations/deploy_migration_test.go (about)

     1  package migrations
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/rs/zerolog"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/onflow/flow-go/cmd/util/ledger/util/registers"
    11  	"github.com/onflow/flow-go/fvm"
    12  	"github.com/onflow/flow-go/fvm/storage/snapshot"
    13  	"github.com/onflow/flow-go/fvm/systemcontracts"
    14  	"github.com/onflow/flow-go/ledger"
    15  	"github.com/onflow/flow-go/ledger/common/convert"
    16  	"github.com/onflow/flow-go/model/flow"
    17  	"github.com/onflow/flow-go/utils/unittest"
    18  )
    19  
    20  func newBootstrapPayloads(
    21  	chainID flow.ChainID,
    22  	bootstrapProcedureOptions ...fvm.BootstrapProcedureOption,
    23  ) ([]*ledger.Payload, error) {
    24  
    25  	ctx := fvm.NewContext(
    26  		fvm.WithChain(chainID.Chain()),
    27  	)
    28  
    29  	vm := fvm.NewVirtualMachine()
    30  
    31  	storageSnapshot := snapshot.MapStorageSnapshot{}
    32  
    33  	bootstrapProcedure := fvm.Bootstrap(
    34  		unittest.ServiceAccountPublicKey,
    35  		bootstrapProcedureOptions...,
    36  	)
    37  
    38  	executionSnapshot, _, err := vm.Run(
    39  		ctx,
    40  		bootstrapProcedure,
    41  		storageSnapshot,
    42  	)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	payloads := make([]*ledger.Payload, 0, len(executionSnapshot.WriteSet))
    48  
    49  	for registerID, registerValue := range executionSnapshot.WriteSet {
    50  		payloadKey := convert.RegisterIDToLedgerKey(registerID)
    51  		payload := ledger.NewPayload(payloadKey, registerValue)
    52  		payloads = append(payloads, payload)
    53  	}
    54  
    55  	return payloads, nil
    56  }
    57  
    58  func TestDeploy(t *testing.T) {
    59  	t.Parallel()
    60  
    61  	const chainID = flow.Emulator
    62  
    63  	chain := chainID.Chain()
    64  
    65  	const nWorker = 2
    66  
    67  	systemContracts := systemcontracts.SystemContractsForChain(chainID)
    68  	serviceAccountAddress := systemContracts.FlowServiceAccount.Address
    69  	fungibleTokenAddress := systemContracts.FungibleToken.Address
    70  
    71  	targetAddress := serviceAccountAddress
    72  
    73  	migration := NewDeploymentMigration(
    74  		chainID,
    75  		Contract{
    76  			Name: "NewContract",
    77  			Code: []byte(fmt.Sprintf(
    78  				`
    79                    import FungibleToken from %s
    80  
    81                    access(all)
    82                    contract NewContract {
    83  
    84                        access(all)
    85                        fun answer(): Int {
    86                            return 42
    87                        }
    88                    }
    89                  `,
    90  				fungibleTokenAddress.HexWithPrefix(),
    91  			)),
    92  		},
    93  		targetAddress,
    94  		map[flow.Address]struct{}{
    95  			targetAddress: {},
    96  		},
    97  		zerolog.New(zerolog.NewTestWriter(t)),
    98  	)
    99  
   100  	bootstrapPayloads, err := newBootstrapPayloads(chainID)
   101  	require.NoError(t, err)
   102  
   103  	filteredPayloads := make([]*ledger.Payload, 0, len(bootstrapPayloads))
   104  
   105  	// TODO: move to NewTransactionBasedMigration
   106  
   107  	// Filter the bootstrapped payloads to only include the target account (service account)
   108  	// and the account where the fungible token is deployed
   109  
   110  	for _, payload := range bootstrapPayloads {
   111  		registerID, _, err := convert.PayloadToRegister(payload)
   112  		require.NoError(t, err)
   113  
   114  		if len(registerID.Owner) > 0 {
   115  			registerAddress := flow.Address([]byte(registerID.Owner))
   116  			switch registerAddress {
   117  			case targetAddress, fungibleTokenAddress:
   118  				filteredPayloads = append(filteredPayloads, payload)
   119  			}
   120  		} else {
   121  			filteredPayloads = append(filteredPayloads, payload)
   122  		}
   123  	}
   124  
   125  	registersByAccount, err := registers.NewByAccountFromPayloads(filteredPayloads)
   126  	require.NoError(t, err)
   127  
   128  	err = migration(registersByAccount)
   129  	require.NoError(t, err)
   130  
   131  	txBody := flow.NewTransactionBody().
   132  		SetScript([]byte(fmt.Sprintf(
   133  			`
   134                import NewContract from %s
   135  
   136                transaction {
   137                    execute {
   138                        log(NewContract.answer())
   139                    }
   140                }
   141              `,
   142  			targetAddress.HexWithPrefix(),
   143  		)))
   144  
   145  	vm := fvm.NewVirtualMachine()
   146  
   147  	storageSnapshot := snapshot.MapStorageSnapshot{}
   148  
   149  	newPayloads := registersByAccount.DestructIntoPayloads(nWorker)
   150  
   151  	for _, newPayload := range newPayloads {
   152  		registerID, registerValue, err := convert.PayloadToRegister(newPayload)
   153  		require.NoError(t, err)
   154  
   155  		storageSnapshot[registerID] = registerValue
   156  	}
   157  
   158  	ctx := fvm.NewContext(
   159  		fvm.WithChain(chain),
   160  		fvm.WithAuthorizationChecksEnabled(false),
   161  		fvm.WithSequenceNumberCheckAndIncrementEnabled(false),
   162  		fvm.WithCadenceLogging(true),
   163  	)
   164  
   165  	_, output, err := vm.Run(
   166  		ctx,
   167  		fvm.Transaction(txBody, 0),
   168  		storageSnapshot,
   169  	)
   170  
   171  	require.NoError(t, err)
   172  	require.NoError(t, output.Err)
   173  	require.Len(t, output.Logs, 1)
   174  	require.Equal(t, "42", output.Logs[0])
   175  }