github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/notary/actor_test.go (about)

     1  package notary
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/google/uuid"
     9  	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
    10  	"github.com/nspcc-dev/neo-go/pkg/core/state"
    11  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    12  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    13  	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
    14  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    15  	"github.com/nspcc-dev/neo-go/pkg/network/payload"
    16  	"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
    17  	"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
    18  	"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
    19  	"github.com/nspcc-dev/neo-go/pkg/smartcontract"
    20  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
    21  	"github.com/nspcc-dev/neo-go/pkg/util"
    22  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
    23  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    24  	"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
    25  	"github.com/nspcc-dev/neo-go/pkg/wallet"
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  type RPCClient struct {
    30  	err     error
    31  	invRes  *result.Invoke
    32  	netFee  int64
    33  	bCount  uint32
    34  	version *result.Version
    35  	hash    util.Uint256
    36  	nhash   util.Uint256
    37  	mirror  bool
    38  	applog  *result.ApplicationLog
    39  }
    40  
    41  func (r *RPCClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
    42  	return r.invRes, r.err
    43  }
    44  func (r *RPCClient) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) {
    45  	return r.invRes, r.err
    46  }
    47  func (r *RPCClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) {
    48  	return r.invRes, r.err
    49  }
    50  func (r *RPCClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) {
    51  	return r.netFee, r.err
    52  }
    53  func (r *RPCClient) GetBlockCount() (uint32, error) {
    54  	return r.bCount, r.err
    55  }
    56  func (r *RPCClient) GetVersion() (*result.Version, error) {
    57  	verCopy := *r.version
    58  	return &verCopy, r.err
    59  }
    60  func (r *RPCClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) {
    61  	return r.hash, r.err
    62  }
    63  func (r *RPCClient) SubmitP2PNotaryRequest(req *payload.P2PNotaryRequest) (util.Uint256, error) {
    64  	if r.mirror {
    65  		return req.FallbackTransaction.Hash(), nil
    66  	}
    67  	return r.nhash, r.err
    68  }
    69  func (r *RPCClient) TerminateSession(sessionID uuid.UUID) (bool, error) {
    70  	return false, nil // Just a stub, unused by actor.
    71  }
    72  func (r *RPCClient) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount int) ([]stackitem.Item, error) {
    73  	return nil, nil // Just a stub, unused by actor.
    74  }
    75  func (r *RPCClient) Context() context.Context {
    76  	return context.Background()
    77  }
    78  func (r *RPCClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) {
    79  	return r.applog, nil
    80  }
    81  
    82  var _ = waiter.RPCPollingBased(&RPCClient{})
    83  
    84  func TestNewActor(t *testing.T) {
    85  	rc := &RPCClient{
    86  		version: &result.Version{
    87  			Protocol: result.Protocol{
    88  				Network:              netmode.UnitTestNet,
    89  				MillisecondsPerBlock: 1000,
    90  				ValidatorsCount:      7,
    91  			},
    92  		},
    93  	}
    94  
    95  	_, err := NewActor(rc, nil, nil)
    96  	require.Error(t, err)
    97  
    98  	var (
    99  		keyz  [4]*keys.PrivateKey
   100  		accs  [4]*wallet.Account
   101  		faccs [4]*wallet.Account
   102  		pkeys [4]*keys.PublicKey
   103  	)
   104  	for i := range accs {
   105  		keyz[i], err = keys.NewPrivateKey()
   106  		require.NoError(t, err)
   107  		accs[i] = wallet.NewAccountFromPrivateKey(keyz[i])
   108  		pkeys[i] = keyz[i].PublicKey()
   109  		faccs[i] = FakeSimpleAccount(pkeys[i])
   110  	}
   111  	var multiAccs [4]*wallet.Account
   112  	for i := range accs {
   113  		multiAccs[i] = &wallet.Account{}
   114  		*multiAccs[i] = *accs[i]
   115  		require.NoError(t, multiAccs[i].ConvertMultisig(smartcontract.GetDefaultHonestNodeCount(len(pkeys)), pkeys[:]))
   116  	}
   117  
   118  	// nil Contract
   119  	badMultiAcc0 := &wallet.Account{}
   120  	*badMultiAcc0 = *multiAccs[0]
   121  	badMultiAcc0.Contract = nil
   122  	_, err = NewActor(rc, []actor.SignerAccount{{
   123  		Signer: transaction.Signer{
   124  			Account: multiAccs[0].Contract.ScriptHash(),
   125  			Scopes:  transaction.CalledByEntry,
   126  		},
   127  		Account: badMultiAcc0,
   128  	}}, accs[0])
   129  	require.Error(t, err)
   130  
   131  	// Non-standard script.
   132  	badMultiAcc0.Contract = &wallet.Contract{}
   133  	*badMultiAcc0.Contract = *multiAccs[0].Contract
   134  	badMultiAcc0.Contract.Script = append(badMultiAcc0.Contract.Script, byte(opcode.NOP))
   135  	badMultiAcc0.Address = address.Uint160ToString(badMultiAcc0.Contract.ScriptHash())
   136  	_, err = NewActor(rc, []actor.SignerAccount{{
   137  		Signer: transaction.Signer{
   138  			Account: badMultiAcc0.Contract.ScriptHash(),
   139  			Scopes:  transaction.CalledByEntry,
   140  		},
   141  		Account: badMultiAcc0,
   142  	}}, accs[0])
   143  	require.Error(t, err)
   144  
   145  	// Too many keys
   146  	var (
   147  		manyKeys  [256]*keys.PrivateKey
   148  		manyPkeys [256]*keys.PublicKey
   149  	)
   150  	for i := range manyKeys {
   151  		manyKeys[i], err = keys.NewPrivateKey()
   152  		require.NoError(t, err)
   153  		manyPkeys[i] = manyKeys[i].PublicKey()
   154  	}
   155  	bigMultiAcc := &wallet.Account{}
   156  	*bigMultiAcc = *wallet.NewAccountFromPrivateKey(manyKeys[0])
   157  	require.NoError(t, bigMultiAcc.ConvertMultisig(129, manyPkeys[:]))
   158  
   159  	_, err = NewActor(rc, []actor.SignerAccount{{
   160  		Signer: transaction.Signer{
   161  			Account: bigMultiAcc.Contract.ScriptHash(),
   162  			Scopes:  transaction.CalledByEntry,
   163  		},
   164  		Account: bigMultiAcc,
   165  	}}, wallet.NewAccountFromPrivateKey(manyKeys[0]))
   166  	require.Error(t, err)
   167  
   168  	// No contract in the simple account.
   169  	badSimple0 := &wallet.Account{}
   170  	*badSimple0 = *accs[0]
   171  	badSimple0.Contract = nil
   172  	_, err = NewActor(rc, []actor.SignerAccount{{
   173  		Signer: transaction.Signer{
   174  			Account: multiAccs[0].Contract.ScriptHash(),
   175  			Scopes:  transaction.CalledByEntry,
   176  		},
   177  		Account: multiAccs[0],
   178  	}}, badSimple0)
   179  	require.Error(t, err)
   180  
   181  	// Simple account that can't sign.
   182  	badSimple0 = FakeSimpleAccount(pkeys[0])
   183  	_, err = NewActor(rc, []actor.SignerAccount{{
   184  		Signer: transaction.Signer{
   185  			Account: multiAccs[0].Contract.ScriptHash(),
   186  			Scopes:  transaction.CalledByEntry,
   187  		},
   188  		Account: multiAccs[0],
   189  	}}, badSimple0)
   190  	require.Error(t, err)
   191  
   192  	// Multisig account instead of simple one.
   193  	_, err = NewActor(rc, []actor.SignerAccount{{
   194  		Signer: transaction.Signer{
   195  			Account: multiAccs[0].Contract.ScriptHash(),
   196  			Scopes:  transaction.CalledByEntry,
   197  		},
   198  		Account: multiAccs[0],
   199  	}}, multiAccs[0])
   200  	require.Error(t, err)
   201  
   202  	// Main actor freaking out on hash mismatch.
   203  	_, err = NewActor(rc, []actor.SignerAccount{{
   204  		Signer: transaction.Signer{
   205  			Account: accs[0].Contract.ScriptHash(),
   206  			Scopes:  transaction.CalledByEntry,
   207  		},
   208  		Account: multiAccs[0],
   209  	}}, accs[0])
   210  	require.Error(t, err)
   211  
   212  	// FB actor freaking out on hash mismatch.
   213  	opts := NewDefaultActorOptions(NewReader(invoker.New(rc, nil)), accs[0])
   214  	opts.FbSigner.Signer.Account = multiAccs[0].Contract.ScriptHash()
   215  	_, err = NewTunedActor(rc, []actor.SignerAccount{{
   216  		Signer: transaction.Signer{
   217  			Account: multiAccs[0].Contract.ScriptHash(),
   218  			Scopes:  transaction.CalledByEntry,
   219  		},
   220  		Account: multiAccs[0],
   221  	}}, opts)
   222  	require.Error(t, err)
   223  
   224  	// Good, one multisig.
   225  	multi0, err := NewActor(rc, []actor.SignerAccount{{
   226  		Signer: transaction.Signer{
   227  			Account: multiAccs[0].Contract.ScriptHash(),
   228  			Scopes:  transaction.CalledByEntry,
   229  		},
   230  		Account: multiAccs[0],
   231  	}}, accs[0])
   232  	require.NoError(t, err)
   233  
   234  	script := []byte{byte(opcode.RET)}
   235  	rc.invRes = &result.Invoke{
   236  		State:       "HALT",
   237  		GasConsumed: 3,
   238  		Script:      script,
   239  		Stack:       []stackitem.Item{stackitem.Make(42)},
   240  	}
   241  	tx, err := multi0.MakeRun(script)
   242  	require.NoError(t, err)
   243  	require.Equal(t, 1, len(tx.Attributes))
   244  	require.Equal(t, transaction.NotaryAssistedT, tx.Attributes[0].Type)
   245  	require.Equal(t, &transaction.NotaryAssisted{NKeys: 4}, tx.Attributes[0].Value)
   246  
   247  	// Good, 4 single sigs with one that can sign and one contract.
   248  	single4, err := NewActor(rc, []actor.SignerAccount{{
   249  		Signer: transaction.Signer{
   250  			Account: accs[0].Contract.ScriptHash(),
   251  			Scopes:  transaction.CalledByEntry,
   252  		},
   253  		Account: accs[0],
   254  	}, {
   255  		Signer: transaction.Signer{
   256  			Account: faccs[1].Contract.ScriptHash(),
   257  			Scopes:  transaction.CalledByEntry,
   258  		},
   259  		Account: faccs[1],
   260  	}, {
   261  		Signer: transaction.Signer{
   262  			Account: faccs[2].Contract.ScriptHash(),
   263  			Scopes:  transaction.CalledByEntry,
   264  		},
   265  		Account: faccs[2],
   266  	}, {
   267  		Signer: transaction.Signer{
   268  			Account: accs[3].Contract.ScriptHash(),
   269  			Scopes:  transaction.CalledByEntry,
   270  		},
   271  		Account: faccs[3],
   272  	}, {
   273  		Signer: transaction.Signer{
   274  			Account: util.Uint160{1, 2, 3},
   275  			Scopes:  transaction.CalledByEntry,
   276  		},
   277  		Account: FakeContractAccount(util.Uint160{1, 2, 3}),
   278  	}}, accs[0])
   279  	require.NoError(t, err)
   280  
   281  	tx, err = single4.MakeRun(script)
   282  	require.NoError(t, err)
   283  	require.Equal(t, 1, len(tx.Attributes))
   284  	require.Equal(t, transaction.NotaryAssistedT, tx.Attributes[0].Type)
   285  	require.Equal(t, &transaction.NotaryAssisted{NKeys: 4}, tx.Attributes[0].Value) // One account can sign, three need to collect additional sigs.
   286  }
   287  
   288  func TestSendRequestExactly(t *testing.T) {
   289  	rc := &RPCClient{
   290  		version: &result.Version{
   291  			Protocol: result.Protocol{
   292  				Network:              netmode.UnitTestNet,
   293  				MillisecondsPerBlock: 1000,
   294  				ValidatorsCount:      7,
   295  			},
   296  		},
   297  	}
   298  
   299  	key0, err := keys.NewPrivateKey()
   300  	require.NoError(t, err)
   301  	key1, err := keys.NewPrivateKey()
   302  	require.NoError(t, err)
   303  
   304  	acc0 := wallet.NewAccountFromPrivateKey(key0)
   305  	facc1 := FakeSimpleAccount(key1.PublicKey())
   306  
   307  	act, err := NewActor(rc, []actor.SignerAccount{{
   308  		Signer: transaction.Signer{
   309  			Account: acc0.Contract.ScriptHash(),
   310  			Scopes:  transaction.None,
   311  		},
   312  		Account: acc0,
   313  	}, {
   314  		Signer: transaction.Signer{
   315  			Account: facc1.Contract.ScriptHash(),
   316  			Scopes:  transaction.CalledByEntry,
   317  		},
   318  		Account: facc1,
   319  	}}, acc0)
   320  	require.NoError(t, err)
   321  
   322  	script := []byte{byte(opcode.RET)}
   323  	mainTx := transaction.New(script, 1)
   324  	fbTx := transaction.New(script, 1)
   325  
   326  	// Hashes mismatch
   327  	_, _, _, err = act.SendRequestExactly(mainTx, fbTx)
   328  	require.Error(t, err)
   329  
   330  	// Error returned
   331  	rc.err = errors.New("")
   332  	_, _, _, err = act.SendRequestExactly(mainTx, fbTx)
   333  	require.Error(t, err)
   334  
   335  	// OK returned
   336  	rc.err = nil
   337  	rc.nhash = fbTx.Hash()
   338  	mHash, fbHash, vub, err := act.SendRequestExactly(mainTx, fbTx)
   339  	require.NoError(t, err)
   340  	require.Equal(t, mainTx.Hash(), mHash)
   341  	require.Equal(t, fbTx.Hash(), fbHash)
   342  	require.Equal(t, mainTx.ValidUntilBlock, vub)
   343  }
   344  
   345  func TestSendRequest(t *testing.T) {
   346  	rc := &RPCClient{
   347  		version: &result.Version{
   348  			Protocol: result.Protocol{
   349  				Network:              netmode.UnitTestNet,
   350  				MillisecondsPerBlock: 1000,
   351  				ValidatorsCount:      7,
   352  			},
   353  		},
   354  		bCount: 42,
   355  	}
   356  
   357  	key0, err := keys.NewPrivateKey()
   358  	require.NoError(t, err)
   359  	key1, err := keys.NewPrivateKey()
   360  	require.NoError(t, err)
   361  
   362  	acc0 := wallet.NewAccountFromPrivateKey(key0)
   363  	facc0 := FakeSimpleAccount(key0.PublicKey())
   364  	facc1 := FakeSimpleAccount(key1.PublicKey())
   365  
   366  	act, err := NewActor(rc, []actor.SignerAccount{{
   367  		Signer: transaction.Signer{
   368  			Account: acc0.Contract.ScriptHash(),
   369  			Scopes:  transaction.None,
   370  		},
   371  		Account: acc0,
   372  	}, {
   373  		Signer: transaction.Signer{
   374  			Account: facc1.Contract.ScriptHash(),
   375  			Scopes:  transaction.CalledByEntry,
   376  		},
   377  		Account: facc1,
   378  	}}, acc0)
   379  	require.NoError(t, err)
   380  
   381  	script := []byte{byte(opcode.RET)}
   382  	rc.invRes = &result.Invoke{
   383  		State:       "HALT",
   384  		GasConsumed: 3,
   385  		Script:      script,
   386  		Stack:       []stackitem.Item{stackitem.Make(42)},
   387  	}
   388  
   389  	mainTx, err := act.MakeRun(script)
   390  	require.NoError(t, err)
   391  
   392  	// No attributes.
   393  	fbTx, err := act.FbActor.MakeUnsignedRun(script, nil)
   394  	require.NoError(t, err)
   395  	fbTx.Attributes = nil
   396  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   397  	require.Error(t, err)
   398  
   399  	// Bad NVB.
   400  	fbTx, err = act.FbActor.MakeUnsignedRun(script, nil)
   401  	require.NoError(t, err)
   402  	fbTx.Attributes[1].Type = transaction.HighPriority
   403  	fbTx.Attributes[1].Value = nil
   404  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   405  	require.Error(t, err)
   406  
   407  	// Bad Conflicts.
   408  	fbTx, err = act.FbActor.MakeUnsignedRun(script, nil)
   409  	require.NoError(t, err)
   410  	fbTx.Attributes[2].Type = transaction.HighPriority
   411  	fbTx.Attributes[2].Value = nil
   412  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   413  	require.Error(t, err)
   414  
   415  	// GetBlockCount error.
   416  	fbTx, err = act.FbActor.MakeUnsignedRun(script, nil)
   417  	require.NoError(t, err)
   418  	rc.err = errors.New("")
   419  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   420  	require.Error(t, err)
   421  
   422  	// Can't sign suddenly.
   423  	rc.err = nil
   424  	acc0Backup := &wallet.Account{}
   425  	*acc0Backup = *acc0
   426  	*acc0 = *facc0
   427  	fbTx, err = act.FbActor.MakeUnsignedRun(script, nil)
   428  	require.NoError(t, err)
   429  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   430  	require.Error(t, err)
   431  
   432  	// Good.
   433  	*acc0 = *acc0Backup
   434  	fbTx, err = act.FbActor.MakeUnsignedRun(script, nil)
   435  	require.NoError(t, err)
   436  	_, _, _, err = act.SendRequest(mainTx, fbTx)
   437  	require.Error(t, err)
   438  }
   439  
   440  func TestNotarize(t *testing.T) {
   441  	rc := &RPCClient{
   442  		version: &result.Version{
   443  			Protocol: result.Protocol{
   444  				Network:              netmode.UnitTestNet,
   445  				MillisecondsPerBlock: 1000,
   446  				ValidatorsCount:      7,
   447  			},
   448  		},
   449  		bCount: 42,
   450  	}
   451  
   452  	key0, err := keys.NewPrivateKey()
   453  	require.NoError(t, err)
   454  	key1, err := keys.NewPrivateKey()
   455  	require.NoError(t, err)
   456  
   457  	acc0 := wallet.NewAccountFromPrivateKey(key0)
   458  	facc1 := FakeSimpleAccount(key1.PublicKey())
   459  
   460  	act, err := NewActor(rc, []actor.SignerAccount{{
   461  		Signer: transaction.Signer{
   462  			Account: acc0.Contract.ScriptHash(),
   463  			Scopes:  transaction.None,
   464  		},
   465  		Account: acc0,
   466  	}, {
   467  		Signer: transaction.Signer{
   468  			Account: facc1.Contract.ScriptHash(),
   469  			Scopes:  transaction.CalledByEntry,
   470  		},
   471  		Account: facc1,
   472  	}}, acc0)
   473  	require.NoError(t, err)
   474  
   475  	script := []byte{byte(opcode.RET)}
   476  
   477  	// Immediate error from MakeRun.
   478  	rc.invRes = &result.Invoke{
   479  		State:       "FAULT",
   480  		GasConsumed: 3,
   481  		Script:      script,
   482  		Stack:       []stackitem.Item{stackitem.Make(42)},
   483  	}
   484  	_, _, _, err = act.Notarize(act.MakeRun(script))
   485  	require.Error(t, err)
   486  
   487  	// Explicitly good transaction. but failure to create a fallback.
   488  	rc.invRes.State = "HALT"
   489  	tx, err := act.MakeRun(script)
   490  	require.NoError(t, err)
   491  
   492  	rc.invRes.State = "FAULT"
   493  	_, _, _, err = act.Notarize(tx, nil)
   494  	require.Error(t, err)
   495  
   496  	// FB hash mismatch from SendRequestExactly.
   497  	rc.invRes.State = "HALT"
   498  	_, _, _, err = act.Notarize(act.MakeRun(script))
   499  	require.Error(t, err)
   500  
   501  	// Good.
   502  	rc.mirror = true
   503  	mHash, fbHash, vub, err := act.Notarize(act.MakeRun(script))
   504  	require.NoError(t, err)
   505  	require.NotEqual(t, util.Uint256{}, mHash)
   506  	require.NotEqual(t, util.Uint256{}, fbHash)
   507  	require.Equal(t, uint32(92), vub)
   508  }
   509  
   510  func TestDefaultActorOptions(t *testing.T) {
   511  	rc := &RPCClient{
   512  		version: &result.Version{
   513  			Protocol: result.Protocol{
   514  				Network:              netmode.UnitTestNet,
   515  				MillisecondsPerBlock: 1000,
   516  				ValidatorsCount:      7,
   517  			},
   518  		},
   519  	}
   520  	acc, err := wallet.NewAccount()
   521  	require.NoError(t, err)
   522  	opts := NewDefaultActorOptions(NewReader(invoker.New(rc, nil)), acc)
   523  	rc.invRes = &result.Invoke{
   524  		State:       "HALT",
   525  		GasConsumed: 3,
   526  		Script:      opts.FbScript,
   527  		Stack:       []stackitem.Item{stackitem.Make(42)},
   528  	}
   529  	tx := transaction.New(opts.FbScript, 1)
   530  	require.Error(t, opts.MainCheckerModifier(&result.Invoke{State: "FAULT"}, tx))
   531  	rc.invRes.State = "FAULT"
   532  	require.Error(t, opts.MainCheckerModifier(&result.Invoke{State: "HALT"}, tx))
   533  	rc.invRes.State = "HALT"
   534  	require.NoError(t, opts.MainCheckerModifier(&result.Invoke{State: "HALT"}, tx))
   535  	require.Equal(t, uint32(42), tx.ValidUntilBlock)
   536  }
   537  
   538  func TestWait(t *testing.T) {
   539  	rc := &RPCClient{version: &result.Version{Protocol: result.Protocol{MillisecondsPerBlock: 1}}}
   540  
   541  	key0, err := keys.NewPrivateKey()
   542  	require.NoError(t, err)
   543  	key1, err := keys.NewPrivateKey()
   544  	require.NoError(t, err)
   545  
   546  	acc0 := wallet.NewAccountFromPrivateKey(key0)
   547  	facc1 := FakeSimpleAccount(key1.PublicKey())
   548  
   549  	act, err := NewActor(rc, []actor.SignerAccount{{
   550  		Signer: transaction.Signer{
   551  			Account: acc0.Contract.ScriptHash(),
   552  			Scopes:  transaction.None,
   553  		},
   554  		Account: acc0,
   555  	}, {
   556  		Signer: transaction.Signer{
   557  			Account: facc1.Contract.ScriptHash(),
   558  			Scopes:  transaction.CalledByEntry,
   559  		},
   560  		Account: facc1,
   561  	}}, acc0)
   562  	require.NoError(t, err)
   563  
   564  	someErr := errors.New("someErr")
   565  	_, err = act.Wait(util.Uint256{}, util.Uint256{}, 0, someErr)
   566  	require.ErrorIs(t, err, someErr)
   567  
   568  	cont := util.Uint256{1, 2, 3}
   569  	ex := state.Execution{
   570  		Trigger:     trigger.Application,
   571  		VMState:     vmstate.Halt,
   572  		GasConsumed: 123,
   573  		Stack:       []stackitem.Item{stackitem.Null{}},
   574  	}
   575  	applog := &result.ApplicationLog{
   576  		Container:     cont,
   577  		IsTransaction: true,
   578  		Executions:    []state.Execution{ex},
   579  	}
   580  	rc.applog = applog
   581  	res, err := act.Wait(util.Uint256{}, util.Uint256{}, 0, nil)
   582  	require.NoError(t, err)
   583  	require.Equal(t, &state.AppExecResult{
   584  		Container: cont,
   585  		Execution: ex,
   586  	}, res)
   587  }