github.com/onflow/flow-go@v0.33.17/engine/execution/testutil/fixtures.go (about)

     1  package testutil
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/onflow/cadence"
    11  	"github.com/onflow/cadence/encoding/ccf"
    12  	jsoncdc "github.com/onflow/cadence/encoding/json"
    13  	"github.com/stretchr/testify/mock"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/onflow/flow-go/crypto"
    17  	"github.com/onflow/flow-go/crypto/hash"
    18  	"github.com/onflow/flow-go/engine/execution"
    19  	"github.com/onflow/flow-go/engine/execution/utils"
    20  	"github.com/onflow/flow-go/fvm"
    21  	"github.com/onflow/flow-go/fvm/environment"
    22  	envMock "github.com/onflow/flow-go/fvm/environment/mock"
    23  	"github.com/onflow/flow-go/fvm/storage/snapshot"
    24  	"github.com/onflow/flow-go/ledger"
    25  	"github.com/onflow/flow-go/ledger/common/pathfinder"
    26  	"github.com/onflow/flow-go/ledger/complete"
    27  	"github.com/onflow/flow-go/model/flow"
    28  	"github.com/onflow/flow-go/module/epochs"
    29  	"github.com/onflow/flow-go/module/executiondatasync/execution_data"
    30  	"github.com/onflow/flow-go/state/protocol"
    31  	protocolMock "github.com/onflow/flow-go/state/protocol/mock"
    32  	"github.com/onflow/flow-go/utils/unittest"
    33  )
    34  
    35  func CreateContractDeploymentTransaction(contractName string, contract string, authorizer flow.Address, chain flow.Chain) *flow.TransactionBody {
    36  
    37  	encoded := hex.EncodeToString([]byte(contract))
    38  
    39  	script := []byte(fmt.Sprintf(`transaction {
    40                prepare(signer: AuthAccount, service: AuthAccount) {
    41                  signer.contracts.add(name: "%s", code: "%s".decodeHex())
    42                }
    43              }`, contractName, encoded))
    44  
    45  	txBody := flow.NewTransactionBody().
    46  		SetScript(script).
    47  		AddAuthorizer(authorizer).
    48  		AddAuthorizer(chain.ServiceAddress())
    49  
    50  	return txBody
    51  }
    52  
    53  func UpdateContractDeploymentTransaction(contractName string, contract string, authorizer flow.Address, chain flow.Chain) *flow.TransactionBody {
    54  	encoded := hex.EncodeToString([]byte(contract))
    55  
    56  	return flow.NewTransactionBody().
    57  		SetScript([]byte(fmt.Sprintf(`transaction {
    58                prepare(signer: AuthAccount, service: AuthAccount) {
    59                  signer.contracts.update__experimental(name: "%s", code: "%s".decodeHex())
    60                }
    61              }`, contractName, encoded)),
    62  		).
    63  		AddAuthorizer(authorizer).
    64  		AddAuthorizer(chain.ServiceAddress())
    65  }
    66  
    67  func UpdateContractUnathorizedDeploymentTransaction(contractName string, contract string, authorizer flow.Address) *flow.TransactionBody {
    68  	encoded := hex.EncodeToString([]byte(contract))
    69  
    70  	return flow.NewTransactionBody().
    71  		SetScript([]byte(fmt.Sprintf(`transaction {
    72                prepare(signer: AuthAccount) {
    73                  signer.contracts.update__experimental(name: "%s", code: "%s".decodeHex())
    74                }
    75              }`, contractName, encoded)),
    76  		).
    77  		AddAuthorizer(authorizer)
    78  }
    79  
    80  func RemoveContractDeploymentTransaction(contractName string, authorizer flow.Address, chain flow.Chain) *flow.TransactionBody {
    81  	return flow.NewTransactionBody().
    82  		SetScript([]byte(fmt.Sprintf(`transaction {
    83                prepare(signer: AuthAccount, service: AuthAccount) {
    84                  signer.contracts.remove(name: "%s")
    85                }
    86              }`, contractName)),
    87  		).
    88  		AddAuthorizer(authorizer).
    89  		AddAuthorizer(chain.ServiceAddress())
    90  }
    91  
    92  func RemoveContractUnathorizedDeploymentTransaction(contractName string, authorizer flow.Address) *flow.TransactionBody {
    93  	return flow.NewTransactionBody().
    94  		SetScript([]byte(fmt.Sprintf(`transaction {
    95                prepare(signer: AuthAccount) {
    96                  signer.contracts.remove(name: "%s")
    97                }
    98              }`, contractName)),
    99  		).
   100  		AddAuthorizer(authorizer)
   101  }
   102  
   103  func CreateUnauthorizedContractDeploymentTransaction(contractName string, contract string, authorizer flow.Address) *flow.TransactionBody {
   104  	encoded := hex.EncodeToString([]byte(contract))
   105  
   106  	return flow.NewTransactionBody().
   107  		SetScript([]byte(fmt.Sprintf(`transaction {
   108                prepare(signer: AuthAccount) {
   109                  signer.contracts.add(name: "%s", code: "%s".decodeHex())
   110                }
   111              }`, contractName, encoded)),
   112  		).
   113  		AddAuthorizer(authorizer)
   114  }
   115  
   116  func SignPayload(
   117  	tx *flow.TransactionBody,
   118  	account flow.Address,
   119  	privateKey flow.AccountPrivateKey,
   120  ) error {
   121  	hasher, err := utils.NewHasher(privateKey.HashAlgo)
   122  	if err != nil {
   123  		return fmt.Errorf("failed to create hasher: %w", err)
   124  	}
   125  
   126  	err = tx.SignPayload(account, 0, privateKey.PrivateKey, hasher)
   127  
   128  	if err != nil {
   129  		return fmt.Errorf("failed to sign transaction: %w", err)
   130  	}
   131  
   132  	return nil
   133  }
   134  
   135  func SignEnvelope(tx *flow.TransactionBody, account flow.Address, privateKey flow.AccountPrivateKey) error {
   136  	hasher, err := utils.NewHasher(privateKey.HashAlgo)
   137  	if err != nil {
   138  		return fmt.Errorf("failed to create hasher: %w", err)
   139  	}
   140  
   141  	err = tx.SignEnvelope(account, 0, privateKey.PrivateKey, hasher)
   142  
   143  	if err != nil {
   144  		return fmt.Errorf("failed to sign transaction: %w", err)
   145  	}
   146  
   147  	return nil
   148  }
   149  
   150  func SignTransaction(
   151  	tx *flow.TransactionBody,
   152  	address flow.Address,
   153  	privateKey flow.AccountPrivateKey,
   154  	seqNum uint64,
   155  ) error {
   156  	tx.SetProposalKey(address, 0, seqNum)
   157  	tx.SetPayer(address)
   158  	return SignEnvelope(tx, address, privateKey)
   159  }
   160  
   161  func SignTransactionAsServiceAccount(tx *flow.TransactionBody, seqNum uint64, chain flow.Chain) error {
   162  	return SignTransaction(tx, chain.ServiceAddress(), unittest.ServiceAccountPrivateKey, seqNum)
   163  }
   164  
   165  // GenerateAccountPrivateKeys generates a number of private keys.
   166  func GenerateAccountPrivateKeys(numberOfPrivateKeys int) ([]flow.AccountPrivateKey, error) {
   167  	var privateKeys []flow.AccountPrivateKey
   168  	for i := 0; i < numberOfPrivateKeys; i++ {
   169  		pk, err := GenerateAccountPrivateKey()
   170  		if err != nil {
   171  			return nil, err
   172  		}
   173  		privateKeys = append(privateKeys, pk)
   174  	}
   175  
   176  	return privateKeys, nil
   177  }
   178  
   179  // GenerateAccountPrivateKey generates a private key.
   180  func GenerateAccountPrivateKey() (flow.AccountPrivateKey, error) {
   181  	seed := make([]byte, crypto.KeyGenSeedMinLen)
   182  	_, err := rand.Read(seed)
   183  	if err != nil {
   184  		return flow.AccountPrivateKey{}, err
   185  	}
   186  	privateKey, err := crypto.GeneratePrivateKey(crypto.ECDSAP256, seed)
   187  	if err != nil {
   188  		return flow.AccountPrivateKey{}, err
   189  	}
   190  	pk := flow.AccountPrivateKey{
   191  		PrivateKey: privateKey,
   192  		SignAlgo:   crypto.ECDSAP256,
   193  		HashAlgo:   hash.SHA2_256,
   194  	}
   195  	return pk, nil
   196  }
   197  
   198  // CreateAccounts inserts accounts into the ledger using the provided private keys.
   199  func CreateAccounts(
   200  	vm fvm.VM,
   201  	snapshotTree snapshot.SnapshotTree,
   202  	privateKeys []flow.AccountPrivateKey,
   203  	chain flow.Chain,
   204  ) (
   205  	snapshot.SnapshotTree,
   206  	[]flow.Address,
   207  	error,
   208  ) {
   209  	return CreateAccountsWithSimpleAddresses(
   210  		vm,
   211  		snapshotTree,
   212  		privateKeys,
   213  		chain)
   214  }
   215  
   216  func CreateAccountsWithSimpleAddresses(
   217  	vm fvm.VM,
   218  	snapshotTree snapshot.SnapshotTree,
   219  	privateKeys []flow.AccountPrivateKey,
   220  	chain flow.Chain,
   221  ) (
   222  	snapshot.SnapshotTree,
   223  	[]flow.Address,
   224  	error,
   225  ) {
   226  	ctx := fvm.NewContext(
   227  		fvm.WithChain(chain),
   228  		fvm.WithAuthorizationChecksEnabled(false),
   229  		fvm.WithSequenceNumberCheckAndIncrementEnabled(false),
   230  	)
   231  
   232  	var accounts []flow.Address
   233  
   234  	scriptTemplate := `
   235          transaction(publicKey: [UInt8]) {
   236              prepare(signer: AuthAccount) {
   237                  let acct = AuthAccount(payer: signer)
   238                  let publicKey2 = PublicKey(
   239                      publicKey: publicKey,
   240                      signatureAlgorithm: SignatureAlgorithm.%s
   241                  )
   242                  acct.keys.add(
   243                      publicKey: publicKey2,
   244                      hashAlgorithm: HashAlgorithm.%s,
   245                      weight: %d.0
   246                  )
   247              }
   248  	    }`
   249  
   250  	serviceAddress := chain.ServiceAddress()
   251  
   252  	for _, privateKey := range privateKeys {
   253  		accountKey := privateKey.PublicKey(fvm.AccountKeyWeightThreshold)
   254  		encPublicKey := accountKey.PublicKey.Encode()
   255  		cadPublicKey := BytesToCadenceArray(encPublicKey)
   256  		encCadPublicKey, _ := jsoncdc.Encode(cadPublicKey)
   257  
   258  		script := []byte(
   259  			fmt.Sprintf(
   260  				scriptTemplate,
   261  				accountKey.SignAlgo.String(),
   262  				accountKey.HashAlgo.String(),
   263  				accountKey.Weight,
   264  			),
   265  		)
   266  
   267  		txBody := flow.NewTransactionBody().
   268  			SetScript(script).
   269  			AddArgument(encCadPublicKey).
   270  			AddAuthorizer(serviceAddress)
   271  
   272  		tx := fvm.Transaction(txBody, 0)
   273  		executionSnapshot, output, err := vm.Run(ctx, tx, snapshotTree)
   274  		if err != nil {
   275  			return snapshotTree, nil, err
   276  		}
   277  
   278  		if output.Err != nil {
   279  			return snapshotTree, nil, fmt.Errorf(
   280  				"failed to create account: %w",
   281  				output.Err)
   282  		}
   283  
   284  		snapshotTree = snapshotTree.Append(executionSnapshot)
   285  
   286  		var addr flow.Address
   287  
   288  		for _, event := range output.Events {
   289  			if event.Type == flow.EventAccountCreated {
   290  				data, err := ccf.Decode(nil, event.Payload)
   291  				if err != nil {
   292  					return snapshotTree, nil, errors.New(
   293  						"error decoding events")
   294  				}
   295  				addr = flow.ConvertAddress(
   296  					data.(cadence.Event).Fields[0].(cadence.Address))
   297  				break
   298  			}
   299  		}
   300  		if addr == flow.EmptyAddress {
   301  			return snapshotTree, nil, errors.New(
   302  				"no account creation event emitted")
   303  		}
   304  		accounts = append(accounts, addr)
   305  	}
   306  
   307  	return snapshotTree, accounts, nil
   308  }
   309  
   310  func RootBootstrappedLedger(
   311  	vm fvm.VM,
   312  	ctx fvm.Context,
   313  	additionalOptions ...fvm.BootstrapProcedureOption,
   314  ) snapshot.SnapshotTree {
   315  	// set 0 clusters to pass n_collectors >= n_clusters check
   316  	epochConfig := epochs.DefaultEpochConfig()
   317  	epochConfig.NumCollectorClusters = 0
   318  
   319  	options := []fvm.BootstrapProcedureOption{
   320  		fvm.WithInitialTokenSupply(unittest.GenesisTokenSupply),
   321  		fvm.WithEpochConfig(epochConfig),
   322  	}
   323  
   324  	options = append(options, additionalOptions...)
   325  
   326  	bootstrap := fvm.Bootstrap(
   327  		unittest.ServiceAccountPublicKey,
   328  		options...,
   329  	)
   330  
   331  	executionSnapshot, _, err := vm.Run(ctx, bootstrap, nil)
   332  	if err != nil {
   333  		panic(err)
   334  	}
   335  	return snapshot.NewSnapshotTree(nil).Append(executionSnapshot)
   336  }
   337  
   338  func BytesToCadenceArray(l []byte) cadence.Array {
   339  	values := make([]cadence.Value, len(l))
   340  	for i, b := range l {
   341  		values[i] = cadence.NewUInt8(b)
   342  	}
   343  
   344  	return cadence.NewArray(values).WithType(cadence.NewVariableSizedArrayType(cadence.NewUInt8Type()))
   345  }
   346  
   347  // CreateAccountCreationTransaction creates a transaction which will create a new account.
   348  //
   349  // This function returns a randomly generated private key and the transaction.
   350  func CreateAccountCreationTransaction(t testing.TB, chain flow.Chain) (flow.AccountPrivateKey, *flow.TransactionBody) {
   351  	accountKey, err := GenerateAccountPrivateKey()
   352  	require.NoError(t, err)
   353  	encPublicKey := accountKey.PublicKey(1000).PublicKey.Encode()
   354  	cadPublicKey := BytesToCadenceArray(encPublicKey)
   355  	encCadPublicKey, err := jsoncdc.Encode(cadPublicKey)
   356  	require.NoError(t, err)
   357  
   358  	// define the cadence script
   359  	script := fmt.Sprintf(`
   360          transaction(publicKey: [UInt8]) {
   361              prepare(signer: AuthAccount) {
   362  				let acct = AuthAccount(payer: signer)
   363                  let publicKey2 = PublicKey(
   364                      publicKey: publicKey,
   365                      signatureAlgorithm: SignatureAlgorithm.%s
   366                  )
   367                  acct.keys.add(
   368                      publicKey: publicKey2,
   369                      hashAlgorithm: HashAlgorithm.%s,
   370                      weight: 1000.0
   371                  )
   372              }
   373  	    }`,
   374  		accountKey.SignAlgo.String(),
   375  		accountKey.HashAlgo.String(),
   376  	)
   377  
   378  	// create the transaction to create the account
   379  	tx := flow.NewTransactionBody().
   380  		SetScript([]byte(script)).
   381  		AddArgument(encCadPublicKey).
   382  		AddAuthorizer(chain.ServiceAddress())
   383  
   384  	return accountKey, tx
   385  }
   386  
   387  // CreateMultiAccountCreationTransaction creates a transaction which will create many (n) new account.
   388  //
   389  // This function returns a randomly generated private key and the transaction.
   390  func CreateMultiAccountCreationTransaction(t *testing.T, chain flow.Chain, n int) (flow.AccountPrivateKey, *flow.TransactionBody) {
   391  	accountKey, err := GenerateAccountPrivateKey()
   392  	require.NoError(t, err)
   393  	encPublicKey := accountKey.PublicKey(1000).PublicKey.Encode()
   394  	cadPublicKey := BytesToCadenceArray(encPublicKey)
   395  	encCadPublicKey, err := jsoncdc.Encode(cadPublicKey)
   396  	require.NoError(t, err)
   397  
   398  	// define the cadence script
   399  	script := fmt.Sprintf(`
   400          transaction(publicKey: [UInt8]) {
   401              prepare(signer: AuthAccount) {
   402                  var i = 0
   403                  while i < %d {
   404                      let account = AuthAccount(payer: signer)
   405                      let publicKey2 = PublicKey(
   406                          publicKey: publicKey,
   407                          signatureAlgorithm: SignatureAlgorithm.%s
   408                      )
   409                      account.keys.add(
   410                          publicKey: publicKey2,
   411                          hashAlgorithm: HashAlgorithm.%s,
   412                          weight: 1000.0
   413                      )
   414                      i = i + 1
   415                  }
   416              }
   417  	    }`,
   418  		n,
   419  		accountKey.SignAlgo.String(),
   420  		accountKey.HashAlgo.String(),
   421  	)
   422  
   423  	// create the transaction to create the account
   424  	tx := flow.NewTransactionBody().
   425  		SetScript([]byte(script)).
   426  		AddArgument(encCadPublicKey).
   427  		AddAuthorizer(chain.ServiceAddress())
   428  
   429  	return accountKey, tx
   430  }
   431  
   432  // CreateAddAnAccountKeyMultipleTimesTransaction generates a tx that adds a key several times to an account.
   433  // this can be used to exhaust an account's storage.
   434  func CreateAddAnAccountKeyMultipleTimesTransaction(t *testing.T, accountKey *flow.AccountPrivateKey, counts int) *flow.TransactionBody {
   435  	script := []byte(fmt.Sprintf(`
   436        transaction(counts: Int, key: [UInt8]) {
   437          prepare(signer: AuthAccount) {
   438            var i = 0
   439            while i < counts {
   440              i = i + 1
   441              let publicKey2 = PublicKey(
   442                publicKey: key,
   443                signatureAlgorithm: SignatureAlgorithm.%s
   444              )
   445              signer.keys.add(
   446                publicKey: publicKey2,
   447                hashAlgorithm: HashAlgorithm.%s,
   448                weight: 1000.0
   449              )
   450  	      }
   451          }
   452        }
   453     	`, accountKey.SignAlgo.String(), accountKey.HashAlgo.String()))
   454  
   455  	arg1, err := jsoncdc.Encode(cadence.NewInt(counts))
   456  	require.NoError(t, err)
   457  
   458  	encPublicKey := accountKey.PublicKey(1000).PublicKey.Encode()
   459  	cadPublicKey := BytesToCadenceArray(encPublicKey)
   460  	arg2, err := jsoncdc.Encode(cadPublicKey)
   461  	require.NoError(t, err)
   462  
   463  	addKeysTx := &flow.TransactionBody{
   464  		Script: script,
   465  	}
   466  	addKeysTx = addKeysTx.AddArgument(arg1).AddArgument(arg2)
   467  	return addKeysTx
   468  }
   469  
   470  // CreateAddAccountKeyTransaction generates a tx that adds a key to an account.
   471  func CreateAddAccountKeyTransaction(t *testing.T, accountKey *flow.AccountPrivateKey) *flow.TransactionBody {
   472  	keyBytes := accountKey.PublicKey(1000).PublicKey.Encode()
   473  
   474  	script := []byte(`
   475          transaction(key: [UInt8]) {
   476            prepare(signer: AuthAccount) {
   477              let acct = AuthAccount(payer: signer)
   478              let publicKey2 = PublicKey(
   479                publicKey: key,
   480                signatureAlgorithm: SignatureAlgorithm.%s
   481              )
   482              signer.keys.add(
   483                publicKey: publicKey2,
   484                hashAlgorithm: HashAlgorithm.%s,
   485                weight: %d.0
   486              )
   487            }
   488          }
   489     	`)
   490  
   491  	arg, err := jsoncdc.Encode(bytesToCadenceArray(keyBytes))
   492  	require.NoError(t, err)
   493  
   494  	addKeysTx := &flow.TransactionBody{
   495  		Script: script,
   496  	}
   497  	addKeysTx = addKeysTx.AddArgument(arg)
   498  
   499  	return addKeysTx
   500  }
   501  
   502  func bytesToCadenceArray(l []byte) cadence.Array {
   503  	values := make([]cadence.Value, len(l))
   504  	for i, b := range l {
   505  		values[i] = cadence.NewUInt8(b)
   506  	}
   507  
   508  	return cadence.NewArray(values)
   509  }
   510  
   511  // TODO(ramtin): when we get rid of BlockExecutionData, this could move to the global unittest fixtures
   512  // TrieUpdates are internal data to the ledger package and should not have leaked into
   513  // packages like uploader in the first place
   514  func ComputationResultFixture(t *testing.T) *execution.ComputationResult {
   515  	startState := unittest.StateCommitmentFixture()
   516  	update1, err := ledger.NewUpdate(
   517  		ledger.State(startState),
   518  		[]ledger.Key{
   519  			ledger.NewKey([]ledger.KeyPart{ledger.NewKeyPart(3, []byte{33})}),
   520  			ledger.NewKey([]ledger.KeyPart{ledger.NewKeyPart(1, []byte{11})}),
   521  			ledger.NewKey([]ledger.KeyPart{ledger.NewKeyPart(2, []byte{1, 1}), ledger.NewKeyPart(3, []byte{2, 5})}),
   522  		},
   523  		[]ledger.Value{
   524  			[]byte{21, 37},
   525  			nil,
   526  			[]byte{3, 3, 3, 3, 3},
   527  		},
   528  	)
   529  	require.NoError(t, err)
   530  
   531  	trieUpdate1, err := pathfinder.UpdateToTrieUpdate(update1, complete.DefaultPathFinderVersion)
   532  	require.NoError(t, err)
   533  
   534  	update2, err := ledger.NewUpdate(
   535  		ledger.State(unittest.StateCommitmentFixture()),
   536  		[]ledger.Key{},
   537  		[]ledger.Value{},
   538  	)
   539  	require.NoError(t, err)
   540  
   541  	trieUpdate2, err := pathfinder.UpdateToTrieUpdate(update2, complete.DefaultPathFinderVersion)
   542  	require.NoError(t, err)
   543  
   544  	update3, err := ledger.NewUpdate(
   545  		ledger.State(unittest.StateCommitmentFixture()),
   546  		[]ledger.Key{
   547  			ledger.NewKey([]ledger.KeyPart{ledger.NewKeyPart(9, []byte{6})}),
   548  		},
   549  		[]ledger.Value{
   550  			[]byte{21, 37},
   551  		},
   552  	)
   553  	require.NoError(t, err)
   554  
   555  	trieUpdate3, err := pathfinder.UpdateToTrieUpdate(update3, complete.DefaultPathFinderVersion)
   556  	require.NoError(t, err)
   557  
   558  	update4, err := ledger.NewUpdate(
   559  		ledger.State(unittest.StateCommitmentFixture()),
   560  		[]ledger.Key{
   561  			ledger.NewKey([]ledger.KeyPart{ledger.NewKeyPart(9, []byte{6})}),
   562  		},
   563  		[]ledger.Value{
   564  			[]byte{21, 37},
   565  		},
   566  	)
   567  	require.NoError(t, err)
   568  
   569  	trieUpdate4, err := pathfinder.UpdateToTrieUpdate(update4, complete.DefaultPathFinderVersion)
   570  	require.NoError(t, err)
   571  
   572  	executableBlock := unittest.ExecutableBlockFixture([][]flow.Identifier{
   573  		{unittest.IdentifierFixture()},
   574  		{unittest.IdentifierFixture()},
   575  		{unittest.IdentifierFixture()},
   576  	}, &startState)
   577  
   578  	blockExecResult := execution.NewPopulatedBlockExecutionResult(executableBlock)
   579  	blockExecResult.CollectionExecutionResultAt(0).AppendTransactionResults(
   580  		flow.EventsList{
   581  			unittest.EventFixture("what", 0, 0, unittest.IdentifierFixture(), 2),
   582  			unittest.EventFixture("ever", 0, 1, unittest.IdentifierFixture(), 22),
   583  		},
   584  		nil,
   585  		nil,
   586  		flow.TransactionResult{
   587  			TransactionID:   unittest.IdentifierFixture(),
   588  			ErrorMessage:    "",
   589  			ComputationUsed: 23,
   590  			MemoryUsed:      101,
   591  		},
   592  	)
   593  	blockExecResult.CollectionExecutionResultAt(1).AppendTransactionResults(
   594  		flow.EventsList{
   595  			unittest.EventFixture("what", 2, 0, unittest.IdentifierFixture(), 2),
   596  			unittest.EventFixture("ever", 2, 1, unittest.IdentifierFixture(), 22),
   597  			unittest.EventFixture("ever", 2, 2, unittest.IdentifierFixture(), 2),
   598  			unittest.EventFixture("ever", 2, 3, unittest.IdentifierFixture(), 22),
   599  		},
   600  		nil,
   601  		nil,
   602  		flow.TransactionResult{
   603  			TransactionID:   unittest.IdentifierFixture(),
   604  			ErrorMessage:    "fail",
   605  			ComputationUsed: 1,
   606  			MemoryUsed:      22,
   607  		},
   608  	)
   609  
   610  	return &execution.ComputationResult{
   611  		BlockExecutionResult: blockExecResult,
   612  		BlockAttestationResult: &execution.BlockAttestationResult{
   613  			BlockExecutionData: &execution_data.BlockExecutionData{
   614  				ChunkExecutionDatas: []*execution_data.ChunkExecutionData{
   615  					{TrieUpdate: trieUpdate1},
   616  					{TrieUpdate: trieUpdate2},
   617  					{TrieUpdate: trieUpdate3},
   618  					{TrieUpdate: trieUpdate4},
   619  				},
   620  			},
   621  		},
   622  		ExecutionReceipt: &flow.ExecutionReceipt{
   623  			ExecutionResult: flow.ExecutionResult{
   624  				Chunks: flow.ChunkList{
   625  					{EndState: unittest.StateCommitmentFixture()},
   626  					{EndState: unittest.StateCommitmentFixture()},
   627  					{EndState: unittest.StateCommitmentFixture()},
   628  					{EndState: unittest.StateCommitmentFixture()},
   629  				},
   630  			},
   631  		},
   632  	}
   633  }
   634  
   635  // EntropyProviderFixture returns an entropy provider mock that
   636  // supports RandomSource().
   637  // If input is nil, a random source fixture is generated.
   638  func EntropyProviderFixture(source []byte) environment.EntropyProvider {
   639  	if source == nil {
   640  		source = unittest.SignatureFixture()
   641  	}
   642  	provider := envMock.EntropyProvider{}
   643  	provider.On("RandomSource").Return(source, nil)
   644  	return &provider
   645  }
   646  
   647  // ProtocolStateWithSourceFixture returns a protocol state mock that only
   648  // supports AtBlockID to return a snapshot mock.
   649  // The snapshot mock only supports RandomSource().
   650  // If input is nil, a random source fixture is generated.
   651  func ProtocolStateWithSourceFixture(source []byte) protocol.State {
   652  	if source == nil {
   653  		source = unittest.SignatureFixture()
   654  	}
   655  	snapshot := &protocolMock.Snapshot{}
   656  	snapshot.On("RandomSource").Return(source, nil)
   657  	state := protocolMock.State{}
   658  	state.On("AtBlockID", mock.Anything).Return(snapshot)
   659  	return &state
   660  }