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