From 84387b24164c198bf74b629377fc49dbeea45433 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 18 Jun 2020 22:17:48 +0300 Subject: [PATCH 1/4] core: set gas limit to transaction.SystemFee for all transactions --- config/protocol.mainnet.yml | 1 - config/protocol.testnet.yml | 1 - pkg/config/protocol_config.go | 5 +---- pkg/core/blockchain.go | 4 +--- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index ad32fd516..8088ae6bb 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -19,7 +19,6 @@ ProtocolConfiguration: - seed5.neo.org:10333 VerifyBlocks: true VerifyTransactions: false - FreeGasLimit: 10.0 MaxTransactionsPerBlock: 500 MaxFreeTransactionsPerBlock: 20 MaxFreeTransactionSize: 1024 diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index d306b9386..41ca65e51 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -19,7 +19,6 @@ ProtocolConfiguration: - seed5t.neo.org:20333 VerifyBlocks: true VerifyTransactions: false - FreeGasLimit: 10.0 MaxTransactionsPerBlock: 500 MaxFreeTransactionsPerBlock: 20 MaxFreeTransactionSize: 1024 diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 151accf24..96cba7502 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -2,7 +2,6 @@ package config import ( "github.com/nspcc-dev/neo-go/pkg/config/netmode" - "github.com/nspcc-dev/neo-go/pkg/util" ) // ProtocolConfiguration represents the protocol config. @@ -10,9 +9,7 @@ type ( ProtocolConfiguration struct { // FeePerExtraByte sets the expected per-byte fee for // transactions exceeding the MaxFreeTransactionSize. - FeePerExtraByte float64 `yaml:"FeePerExtraByte"` - // FreeGasLimit is an amount of GAS which can be spent for free. - FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"` + FeePerExtraByte float64 `yaml:"FeePerExtraByte"` LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` Magic netmode.Magic `yaml:"Magic"` MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 2bb20863d..cfec49171 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -605,9 +605,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { v := SpawnVM(systemInterop) v.LoadScriptWithFlags(tx.Script, smartcontract.All) v.SetPriceGetter(getPrice) - if bc.config.FreeGasLimit > 0 { - v.GasLimit = bc.config.FreeGasLimit + tx.SystemFee - } + v.GasLimit = tx.SystemFee err := v.Run() if !v.HasFailed() { From 2f724b792c62f465ece9627fb82d03640ab02bb7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 18 Jun 2020 22:21:19 +0300 Subject: [PATCH 2/4] core: remove config fields related to free transactions In NEO3 every transaction must have some gas attached. Closes #1064. --- config/protocol.mainnet.yml | 3 --- config/protocol.testnet.yml | 3 --- pkg/config/protocol_config.go | 9 +-------- pkg/core/blockchain.go | 29 ----------------------------- 4 files changed, 1 insertion(+), 43 deletions(-) diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index 8088ae6bb..0c8644653 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -20,9 +20,6 @@ ProtocolConfiguration: VerifyBlocks: true VerifyTransactions: false MaxTransactionsPerBlock: 500 - MaxFreeTransactionsPerBlock: 20 - MaxFreeTransactionSize: 1024 - FeePerExtraByte: 0.00001 ApplicationConfiguration: # LogPath could be set up in case you need stdout logs to some proper file. diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index 41ca65e51..4e6f63d71 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -20,9 +20,6 @@ ProtocolConfiguration: VerifyBlocks: true VerifyTransactions: false MaxTransactionsPerBlock: 500 - MaxFreeTransactionsPerBlock: 20 - MaxFreeTransactionSize: 1024 - FeePerExtraByte: 0.00001 ApplicationConfiguration: # LogPath could be set up in case you need stdout logs to some proper file. diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 96cba7502..78bda30b7 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -7,17 +7,10 @@ import ( // ProtocolConfiguration represents the protocol config. type ( ProtocolConfiguration struct { - // FeePerExtraByte sets the expected per-byte fee for - // transactions exceeding the MaxFreeTransactionSize. - FeePerExtraByte float64 `yaml:"FeePerExtraByte"` LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` Magic netmode.Magic `yaml:"Magic"` MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` - // Maximum size of low priority transaction in bytes. - MaxFreeTransactionSize int `yaml:"MaxFreeTransactionSize"` - // Maximum number of low priority transactions accepted into block. - MaxFreeTransactionsPerBlock int `yaml:"MaxFreeTransactionsPerBlock"` - MemPoolSize int `yaml:"MemPoolSize"` + MemPoolSize int `yaml:"MemPoolSize"` // SaveStorageBatch enables storage batch saving before every persist. SaveStorageBatch bool `yaml:"SaveStorageBatch"` SecondsPerBlock int `yaml:"SecondsPerBlock"` diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index cfec49171..8969d1aa0 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -156,18 +156,6 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L cfg.MaxTransactionsPerBlock = 0 log.Info("MaxTransactionsPerBlock is not set or wrong, setting default value (unlimited)", zap.Int("MaxTransactionsPerBlock", cfg.MaxTransactionsPerBlock)) } - if cfg.MaxFreeTransactionsPerBlock <= 0 { - cfg.MaxFreeTransactionsPerBlock = 0 - log.Info("MaxFreeTransactionsPerBlock is not set or wrong, setting default value (unlimited)", zap.Int("MaxFreeTransactionsPerBlock", cfg.MaxFreeTransactionsPerBlock)) - } - if cfg.MaxFreeTransactionSize <= 0 { - cfg.MaxFreeTransactionSize = 0 - log.Info("MaxFreeTransactionSize is not set or wrong, setting default value (unlimited)", zap.Int("MaxFreeTransactionSize", cfg.MaxFreeTransactionSize)) - } - if cfg.FeePerExtraByte <= 0 { - cfg.FeePerExtraByte = 0 - log.Info("FeePerExtraByte is not set or wrong, setting default value", zap.Float64("FeePerExtraByte", cfg.FeePerExtraByte)) - } bc := &Blockchain{ config: cfg, dao: dao.NewSimple(s, cfg.Magic), @@ -1117,15 +1105,6 @@ func (bc *Blockchain) ApplyPolicyToTxSet(txes []*transaction.Transaction) []*tra if bc.config.MaxTransactionsPerBlock != 0 && len(txes) > bc.config.MaxTransactionsPerBlock { txes = txes[:bc.config.MaxTransactionsPerBlock] } - maxFree := bc.config.MaxFreeTransactionsPerBlock - if maxFree != 0 { - lowStart := sort.Search(len(txes), func(i int) bool { - return bc.IsLowPriority(txes[i].NetworkFee) - }) - if lowStart+maxFree < len(txes) { - txes = txes[:lowStart+maxFree] - } - } return txes } @@ -1225,14 +1204,6 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error { return err } // Policying. - txSize := io.GetVarSize(t) - maxFree := bc.config.MaxFreeTransactionSize - if maxFree != 0 && txSize > maxFree { - if bc.IsLowPriority(t.NetworkFee) || - t.NetworkFee < util.Fixed8FromFloat(bc.config.FeePerExtraByte)*util.Fixed8(txSize-maxFree) { - return ErrPolicy - } - } if err := bc.memPool.Add(t, bc); err != nil { switch err { case mempool.ErrOOM: From 5354352d6335cbcb86ac71010fbea2a147791afa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 18 Jun 2020 22:32:29 +0300 Subject: [PATCH 3/4] core: remove transaction priority There is no such thing as high/low priority transactions, as there are no free transactions anymore and they are ordered by fees contained in transaction itself. Closes #1063. --- config/protocol.mainnet.yml | 1 - config/protocol.privnet.docker.four.yml | 1 - config/protocol.privnet.docker.one.yml | 1 - config/protocol.privnet.docker.single.yml | 1 - config/protocol.privnet.docker.three.yml | 1 - config/protocol.privnet.docker.two.yml | 1 - config/protocol.privnet.yml | 1 - config/protocol.testnet.yml | 1 - config/protocol.unit_testnet.yml | 1 - pkg/config/protocol_config.go | 1 - pkg/consensus/consensus_test.go | 4 ---- pkg/core/blockchain.go | 6 ------ pkg/core/mempool/feer.go | 1 - pkg/core/mempool/mem_pool.go | 10 ---------- pkg/core/mempool/mem_pool_test.go | 23 ++++++++--------------- pkg/network/helper_test.go | 4 ---- pkg/rpc/server/server_helper_test.go | 4 ---- 17 files changed, 8 insertions(+), 54 deletions(-) diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index 0c8644653..c71bc54c9 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 5195086 SecondsPerBlock: 15 - LowPriorityThreshold: 0.001 MemPoolSize: 50000 StandbyValidators: - 03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c diff --git a/config/protocol.privnet.docker.four.yml b/config/protocol.privnet.docker.four.yml index 855f91b4b..ea879039f 100644 --- a/config/protocol.privnet.docker.four.yml +++ b/config/protocol.privnet.docker.four.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.privnet.docker.one.yml b/config/protocol.privnet.docker.one.yml index f6e6af47e..69e7b9efc 100644 --- a/config/protocol.privnet.docker.one.yml +++ b/config/protocol.privnet.docker.one.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.privnet.docker.single.yml b/config/protocol.privnet.docker.single.yml index c354d944c..ed03d2dca 100644 --- a/config/protocol.privnet.docker.single.yml +++ b/config/protocol.privnet.docker.single.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 1 - LowPriorityThreshold: 0.001 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.privnet.docker.three.yml b/config/protocol.privnet.docker.three.yml index a6411b115..9f4b0da88 100644 --- a/config/protocol.privnet.docker.three.yml +++ b/config/protocol.privnet.docker.three.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.privnet.docker.two.yml b/config/protocol.privnet.docker.two.yml index ab7d6394b..cae6428b9 100644 --- a/config/protocol.privnet.docker.two.yml +++ b/config/protocol.privnet.docker.two.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.privnet.yml b/config/protocol.privnet.yml index 9071f250f..7d95a03f3 100644 --- a/config/protocol.privnet.yml +++ b/config/protocol.privnet.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 56753 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index 4e6f63d71..36d7c46ab 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 1951352142 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d diff --git a/config/protocol.unit_testnet.yml b/config/protocol.unit_testnet.yml index 7eccfffbc..23c924c31 100644 --- a/config/protocol.unit_testnet.yml +++ b/config/protocol.unit_testnet.yml @@ -1,7 +1,6 @@ ProtocolConfiguration: Magic: 42 SecondsPerBlock: 15 - LowPriorityThreshold: 0.000 MemPoolSize: 50000 StandbyValidators: - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 78bda30b7..293664cdd 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -7,7 +7,6 @@ import ( // ProtocolConfiguration represents the protocol config. type ( ProtocolConfiguration struct { - LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` Magic netmode.Magic `yaml:"Magic"` MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` MemPoolSize int `yaml:"MemPoolSize"` diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index d59ac3825..2db405ef2 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -229,10 +229,6 @@ func newTestChain(t *testing.T) *core.Blockchain { return chain } -type feer struct{} - -func (fs *feer) IsLowPriority(util.Fixed8) bool { return false } - var neoOwner = testchain.MultisigScriptHash() func addSender(t *testing.T, txs ...*transaction.Transaction) { diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 8969d1aa0..7bf69325e 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1088,12 +1088,6 @@ func (bc *Blockchain) FeePerByte() util.Fixed8 { return util.Fixed8(1000) } -// IsLowPriority checks given fee for being less than configured -// LowPriorityThreshold. -func (bc *Blockchain) IsLowPriority(fee util.Fixed8) bool { - return fee < util.Fixed8FromFloat(bc.GetConfig().LowPriorityThreshold) -} - // GetMemPool returns the memory pool of the blockchain. func (bc *Blockchain) GetMemPool() *mempool.Pool { return &bc.memPool diff --git a/pkg/core/mempool/feer.go b/pkg/core/mempool/feer.go index 91d81e4e8..556432566 100644 --- a/pkg/core/mempool/feer.go +++ b/pkg/core/mempool/feer.go @@ -6,7 +6,6 @@ import ( // Feer is an interface that abstract the implementation of the fee calculation. type Feer interface { - IsLowPriority(util.Fixed8) bool FeePerByte() util.Fixed8 GetUtilityTokenBalance(util.Uint160) util.Fixed8 } diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index 748c8b811..5000fb4b5 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -27,7 +27,6 @@ var ( type item struct { txn *transaction.Transaction timeStamp time.Time - isLowPrio bool } // items is a slice of item. @@ -63,14 +62,6 @@ func (p *item) CompareTo(otherP *item) int { return 1 } - if !p.isLowPrio && otherP.isLowPrio { - return 1 - } - - if p.isLowPrio && !otherP.isLowPrio { - return -1 - } - // Fees sorted ascending. if ret := p.txn.FeePerByte().CompareTo(otherP.txn.FeePerByte()); ret != 0 { return ret @@ -151,7 +142,6 @@ func (mp *Pool) Add(t *transaction.Transaction, fee Feer) error { txn: t, timeStamp: time.Now().UTC(), } - pItem.isLowPrio = fee.IsLowPriority(pItem.txn.NetworkFee) mp.lock.Lock() if !mp.checkTxConflicts(t, fee) { mp.lock.Unlock() diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 2df37ad9d..bae5196f3 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -13,12 +13,7 @@ import ( ) type FeerStub struct { - lowPriority bool - feePerByte util.Fixed8 -} - -func (fs *FeerStub) IsLowPriority(util.Fixed8) bool { - return fs.lowPriority + feePerByte util.Fixed8 } func (fs *FeerStub) FeePerByte() util.Fixed8 { @@ -50,14 +45,12 @@ func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) { } func TestMemPoolAddRemove(t *testing.T) { - var fs = &FeerStub{lowPriority: false} - t.Run("low priority", func(t *testing.T) { testMemPoolAddRemoveWithFeer(t, fs) }) - fs.lowPriority = true - t.Run("high priority", func(t *testing.T) { testMemPoolAddRemoveWithFeer(t, fs) }) + var fs = &FeerStub{} + testMemPoolAddRemoveWithFeer(t, fs) } func TestOverCapacity(t *testing.T) { - var fs = &FeerStub{lowPriority: true} + var fs = &FeerStub{} const mempoolSize = 10 mp := NewMemPool(mempoolSize) @@ -110,9 +103,9 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) // High priority always wins over low priority. - fs.lowPriority = false for i := 0; i < mempoolSize; i++ { tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx.NetworkFee = util.Fixed8FromFloat(0.00008) tx.Nonce = txcnt txcnt++ require.NoError(t, mp.Add(tx, fs)) @@ -120,16 +113,16 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) } // Good luck with low priority now. - fs.lowPriority = true tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) tx.Nonce = txcnt + tx.NetworkFee = util.Fixed8FromFloat(0.00007) require.Error(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) } func TestGetVerified(t *testing.T) { - var fs = &FeerStub{lowPriority: true} + var fs = &FeerStub{} const mempoolSize = 10 mp := NewMemPool(mempoolSize) @@ -152,7 +145,7 @@ func TestGetVerified(t *testing.T) { } func TestRemoveStale(t *testing.T) { - var fs = &FeerStub{lowPriority: true} + var fs = &FeerStub{} const mempoolSize = 10 mp := NewMemPool(mempoolSize) diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 70ad94bb8..e2cfd12d1 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -123,10 +123,6 @@ func (chain testChain) GetMemPool() *mempool.Pool { panic("TODO") } -func (chain testChain) IsLowPriority(util.Fixed8) bool { - panic("TODO") -} - func (chain testChain) GetGoverningTokenBalance(acc util.Uint160) (util.Fixed8, uint32) { panic("TODO") } diff --git a/pkg/rpc/server/server_helper_test.go b/pkg/rpc/server/server_helper_test.go index 813b46839..6d0258626 100644 --- a/pkg/rpc/server/server_helper_test.go +++ b/pkg/rpc/server/server_helper_test.go @@ -85,10 +85,6 @@ func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *http type FeerStub struct{} -func (fs *FeerStub) IsLowPriority(util.Fixed8) bool { - return false -} - func (fs *FeerStub) FeePerByte() util.Fixed8 { return 0 } From e7d8bb92f67f05a078952e3c86f6a0a1255542c8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 18 Jun 2020 22:43:04 +0300 Subject: [PATCH 4/4] core/tests: extend native contract test Check if native contract's method price is taken into account. --- pkg/core/native_contract_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/core/native_contract_test.go b/pkg/core/native_contract_test.go index a08556a0d..929413a1f 100644 --- a/pkg/core/native_contract_test.go +++ b/pkg/core/native_contract_test.go @@ -107,7 +107,14 @@ func TestNativeContract_Invoke(t *testing.T) { tx.ValidUntilBlock = validUntil require.NoError(t, addSender(tx)) require.NoError(t, signTx(chain, tx)) - b := chain.newBlock(tx) + + // Enough for Call and other opcodes, but not enough for "sum" call. + tx2 := transaction.New(chain.GetConfig().Magic, script, testSumPrice*2) + tx2.ValidUntilBlock = chain.blockHeight + 1 + require.NoError(t, addSender(tx2)) + require.NoError(t, signTx(chain, tx2)) + + b := chain.newBlock(tx, tx2) require.NoError(t, chain.AddBlock(b)) res, err := chain.GetAppExecResult(tx.Hash()) @@ -117,6 +124,10 @@ func TestNativeContract_Invoke(t *testing.T) { require.Equal(t, smartcontract.IntegerType, res.Stack[0].Type) require.EqualValues(t, 42, res.Stack[0].Value) + res, err = chain.GetAppExecResult(tx2.Hash()) + require.NoError(t, err) + require.Equal(t, "FAULT", res.VMState) + require.NoError(t, chain.persist()) select { case index := <-tn.blocks: