Skip to content

Commit ba582e6

Browse files
committed
[execution] Improve caching in accessors + simplify code
1 parent 06c0cde commit ba582e6

File tree

18 files changed

+488
-1081
lines changed

18 files changed

+488
-1081
lines changed

nil/internal/collate/block_listener.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,9 @@ func SetBlockRequestHandler(
212212
}
213213
defer tx.Rollback()
214214

215-
acc := accessor.RawAccess(tx, shardId).
216-
GetBlock().
217-
WithOutTransactions().
218-
WithInTransactions().
219-
WithChildBlocks().
220-
WithConfig()
221-
215+
acc := accessor.RawAccess(tx, shardId)
222216
for id := blockReq.GetId(); ; id++ {
223-
resp, err := acc.ByNumber(types.BlockNumber(id))
217+
resp, err := acc.GetFullBlockByNumber(types.BlockNumber(id))
224218
if err != nil {
225219
if !errors.Is(err, db.ErrKeyNotFound) {
226220
logError(logger, err, "DB error")
@@ -229,11 +223,11 @@ func SetBlockRequestHandler(
229223
}
230224

231225
b := &pb.RawFullBlock{
232-
BlockBytes: resp.Block(),
233-
OutTransactionsBytes: resp.OutTransactions(),
234-
InTransactionsBytes: resp.InTransactions(),
235-
ChildBlocks: pb.PackHashes(resp.ChildBlocks()),
236-
Config: resp.Config(),
226+
BlockBytes: resp.Block,
227+
OutTransactionsBytes: resp.OutTransactions,
228+
InTransactionsBytes: resp.InTransactions,
229+
ChildBlocks: pb.PackHashes(resp.ChildBlocks),
230+
Config: resp.Config,
237231
}
238232

239233
if err := writeBlockToStream(s, b); err != nil {

nil/internal/collate/proposer_test.go

Lines changed: 22 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package collate
22

33
import (
4+
"slices"
45
"testing"
56

67
"github.com/NilFoundation/nil/nil/common"
@@ -97,24 +98,24 @@ func (s *ProposerTestSuite) TestCollator() {
9798
p := newTestProposer(params, pool)
9899
shardId := p.params.ShardId
99100

100-
generateBlock := func() *execution.Proposal {
101+
generateBlock := func() (*execution.Proposal, *execution.BlockGenerationResult) {
101102
proposal := s.generateProposal(p)
102103

103104
tx, err := s.db.CreateRoTx(s.T().Context())
104105
s.Require().NoError(err)
105106
defer tx.Rollback()
106107

107-
block, err := db.ReadBlock(tx, shardId, proposal.PrevBlockHash)
108+
prevBlock, err := db.ReadBlock(tx, shardId, proposal.PrevBlockHash)
108109
s.Require().NoError(err)
109110

110-
blockGenerator, err := execution.NewBlockGenerator(s.T().Context(), params.BlockGeneratorParams, s.db, block)
111+
gen, err := execution.NewBlockGenerator(s.T().Context(), params.BlockGeneratorParams, s.db, prevBlock)
111112
s.Require().NoError(err)
112-
defer blockGenerator.Rollback()
113+
defer gen.Rollback()
113114

114-
_, err = blockGenerator.GenerateBlock(proposal, &types.ConsensusParams{})
115+
block, err := gen.GenerateBlock(proposal, &types.ConsensusParams{})
115116
s.Require().NoError(err)
116117

117-
return proposal
118+
return proposal, block
118119
}
119120

120121
s.Run("GenerateZeroState", func() {
@@ -133,9 +134,9 @@ func (s *ProposerTestSuite) TestCollator() {
133134
pool.Reset()
134135
pool.Add(m1, m2)
135136

136-
proposal := generateBlock()
137-
r1 = s.checkReceipt(shardId, m1)
138-
r2 = s.checkReceipt(shardId, m2)
137+
proposal, res := generateBlock()
138+
r1 = s.checkReceipt(res, m1)
139+
r2 = s.checkReceipt(res, m2)
139140
s.Equal(pool.Txns, proposal.ExternalTxns)
140141

141142
// Each transaction subtracts its value + actual gas used from the balance.
@@ -160,15 +161,13 @@ func (s *ProposerTestSuite) TestCollator() {
160161

161162
balance = balance.Add(r1.Forwarded).Add(r2.Forwarded)
162163
s.Equal(balance, s.getMainBalance())
163-
164-
s.checkSeqno(shardId)
165164
})
166165

167166
s.Run("DoNotProcessDuplicates", func() {
168167
pool.Reset()
169168
pool.Add(m1, m2)
170169

171-
proposal := generateBlock()
170+
proposal, _ := generateBlock()
172171
s.Empty(proposal.ExternalTxns)
173172
s.Empty(proposal.InternalTxns)
174173
s.Empty(proposal.ForwardTxns)
@@ -183,36 +182,17 @@ func (s *ProposerTestSuite) TestCollator() {
183182
pool.Reset()
184183
pool.Add(m)
185184

186-
generateBlock()
187-
s.checkReceipt(shardId, m)
185+
_, res := generateBlock()
186+
s.checkReceipt(res, m)
188187
})
189188

190189
s.Run("Execute", func() {
191190
m := execution.NewExecutionTransaction(to, to, 1, contracts.NewCounterAddCallData(s.T(), 3))
192191
pool.Reset()
193192
pool.Add(m)
194193

195-
generateBlock()
196-
s.checkReceipt(shardId, m)
197-
})
198-
199-
s.Run("CheckRefundsSeqno", func() {
200-
m01 := execution.NewSendMoneyTransaction(s.T(), to, 2)
201-
m02 := execution.NewSendMoneyTransaction(s.T(), to, 3)
202-
pool.Reset()
203-
pool.Add(m01, m02)
204-
205-
// send tokens
206-
generateBlock()
207-
208-
// process internal transactions
209-
generateBlock()
210-
211-
// process refunds
212-
generateBlock()
213-
214-
// check refunds seqnos
215-
s.checkSeqno(shardId)
194+
_, res := generateBlock()
195+
s.checkReceipt(res, m)
216196
})
217197
}
218198

@@ -245,52 +225,16 @@ func (s *ProposerTestSuite) getBalance(shardId types.ShardId, addr types.Address
245225
return acc.Balance
246226
}
247227

248-
func (s *ProposerTestSuite) checkSeqno(shardId types.ShardId) {
249-
s.T().Helper()
250-
251-
tx, err := s.db.CreateRoTx(s.T().Context())
252-
s.Require().NoError(err)
253-
defer tx.Rollback()
254-
255-
sa := execution.NewStateAccessor()
256-
blockHash, err := db.ReadLastBlockHash(tx, shardId)
257-
s.Require().NoError(err)
258-
259-
block, err := sa.Access(tx, shardId).GetBlock().WithInTransactions().WithOutTransactions().ByHash(blockHash)
260-
s.Require().NoError(err)
261-
262-
check := func(txns []*types.Transaction) {
263-
if len(txns) == 0 {
264-
return
265-
}
266-
seqno := txns[0].Seqno
267-
for _, m := range txns {
268-
s.Require().Equal(seqno, m.Seqno)
269-
seqno++
270-
}
271-
}
272-
273-
check(block.InTransactions())
274-
check(block.OutTransactions())
275-
}
276-
277-
func (s *ProposerTestSuite) checkReceipt(shardId types.ShardId, m *types.Transaction) *types.Receipt {
228+
func (s *ProposerTestSuite) checkReceipt(genRes *execution.BlockGenerationResult, m *types.Transaction) *types.Receipt {
278229
s.T().Helper()
279230

280-
tx, err := s.db.CreateRoTx(s.T().Context())
281-
s.Require().NoError(err)
282-
defer tx.Rollback()
283-
284-
sa := execution.NewStateAccessor()
285-
txnData, err := sa.Access(tx, m.From.ShardId()).GetInTransaction().ByHash(m.Hash())
286-
s.Require().NoError(err)
231+
hash := m.Hash()
232+
idx := slices.IndexFunc(genRes.Receipts, func(r *types.Receipt) bool {
233+
return r.TxnHash == hash
234+
})
235+
s.Require().GreaterOrEqual(idx, 0, "receipt not found for transaction %s", hash)
287236

288-
receiptsTrie := execution.NewDbReceiptTrieReader(tx, shardId)
289-
s.Require().NoError(receiptsTrie.SetRootHash(txnData.Block().ReceiptsRoot))
290-
receipt, err := receiptsTrie.Fetch(txnData.Index())
291-
s.Require().NoError(err)
292-
s.Equal(m.Hash(), receipt.TxnHash)
293-
return receipt
237+
return genRes.Receipts[idx]
294238
}
295239

296240
func TestProposer(t *testing.T) {

nil/internal/execution/block_cache.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ func getHashFn(es *ExecutionState, ref *types.Block) func(n uint64) (common.Hash
3535
lastKnownHash := cache[len(cache)-1]
3636

3737
for {
38-
data, err := es.shardAccessor.GetBlock().ByHash(lastKnownHash)
38+
b, err := es.shardAccessor.GetBlockHeaderByHash(lastKnownHash)
3939
if errors.Is(err, db.ErrKeyNotFound) {
4040
break
4141
}
4242
if err != nil {
4343
return common.EmptyHash, err
4444
}
4545

46-
cache = append(cache, data.Block().PrevBlock)
47-
lastKnownHash = data.Block().PrevBlock
48-
lastKnownNumber := data.Block().Id.Uint64() - 1
46+
cache = append(cache, b.PrevBlock)
47+
lastKnownHash = b.PrevBlock
48+
lastKnownNumber := b.Id.Uint64() - 1
4949
if n == lastKnownNumber {
5050
return lastKnownHash, nil
5151
}

nil/internal/execution/block_generator.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type BlockGenerationResult struct {
6060
InTxnHashes []common.Hash
6161
OutTxns []*types.Transaction
6262
OutTxnHashes []common.Hash
63+
Receipts []*types.Receipt
6364
ConfigParams map[string][]byte
6465

6566
Counters *BlockGeneratorCounters

nil/internal/execution/execution_state_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,13 @@ func (s *SuiteExecutionState) TestExecState() {
9292
})
9393

9494
s.Run("CheckTransactions", func() {
95-
data, err := es.shardAccessor.GetBlock().ByHash(blockRes.BlockHash)
95+
block, err := es.shardAccessor.GetBlockHeaderByHash(blockRes.BlockHash)
9696
s.Require().NoError(err)
97-
s.Require().NotNil(data)
98-
s.Require().NotNil(data.Block())
9997

10098
transactionsRoot := NewDbTransactionTrieReader(tx, es.ShardId)
101-
s.Require().NoError(transactionsRoot.SetRootHash(data.Block().InTransactionsRoot))
99+
s.Require().NoError(transactionsRoot.SetRootHash(block.InTransactionsRoot))
102100
receiptsRoot := NewDbReceiptTrieReader(tx, es.ShardId)
103-
s.Require().NoError(receiptsRoot.SetRootHash(data.Block().ReceiptsRoot))
101+
s.Require().NoError(receiptsRoot.SetRootHash(block.ReceiptsRoot))
104102

105103
var transactionIndex types.TransactionIndex
106104
for {

nil/internal/execution/state.go

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type ExecutionState struct {
125125
// Tracing hooks set for every EVM created during execution
126126
EvmTracingHooks *tracing.Hooks
127127

128-
shardAccessor *shardAccessor
128+
shardAccessor ShardAccessor
129129

130130
// Pointer to currently executed VM
131131
evm *vm.EVM
@@ -256,17 +256,15 @@ type revision struct {
256256

257257
// NewEVMBlockContext creates a new context for use in the EVM.
258258
func NewEVMBlockContext(es *ExecutionState) (*vm.BlockContext, error) {
259-
data, err := es.shardAccessor.GetBlock().ByHash(es.PrevBlock)
259+
header, err := es.shardAccessor.GetBlockHeaderByHash(es.PrevBlock)
260260
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
261261
return nil, err
262262
}
263263

264264
currentBlockId := uint64(0)
265-
var header *types.Block
266265
time := uint64(0)
267266
rollbackCounter := uint32(0)
268267
if err == nil {
269-
header = data.Block()
270268
currentBlockId = header.Id.Uint64() + 1
271269
// TODO: we need to use header.Timestamp instead of but it's always zero for now.
272270
// Let's return some kind of logical timestamp (monotonic increasing block number).
@@ -393,7 +391,7 @@ func (ca *DbContractAccessor) UpdateContracts(contracts map[types.Address]*Accou
393391
}
394392

395393
func (es *ExecutionState) initTries(params *StateParams) error {
396-
data, err := es.shardAccessor.GetBlock().ByHash(es.PrevBlock)
394+
block, err := es.shardAccessor.GetBlockHeaderByHash(es.PrevBlock)
397395
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
398396
return err
399397
}
@@ -403,7 +401,6 @@ func (es *ExecutionState) initTries(params *StateParams) error {
403401
outTransactionsRoot := mpt.EmptyRootHash
404402
inTransactionsRoot := mpt.EmptyRootHash
405403
if err == nil {
406-
block := data.Block()
407404
smartContractsRoot = block.SmartContractsRoot
408405
outTransactionsRoot = block.OutTransactionsRoot
409406
inTransactionsRoot = block.InTransactionsRoot
@@ -481,7 +478,7 @@ func (es *ExecutionState) setAccountObject(acc *AccountState) {
481478
es.Accounts[acc.address] = acc
482479
}
483480

484-
func (es *ExecutionState) AddAddressToAccessList(addr types.Address) {
481+
func (es *ExecutionState) AddAddressToAccessList(types.Address) {
485482
}
486483

487484
// AddBalance adds amount to the account associated with addr.
@@ -530,10 +527,10 @@ func (es *ExecutionState) GetRefund() uint64 {
530527
return es.refund
531528
}
532529

533-
func (es *ExecutionState) AddSlotToAccessList(addr types.Address, slot common.Hash) {
530+
func (es *ExecutionState) AddSlotToAccessList(types.Address, common.Hash) {
534531
}
535532

536-
func (es *ExecutionState) AddressInAccessList(addr types.Address) bool {
533+
func (es *ExecutionState) AddressInAccessList(types.Address) bool {
537534
return true // FIXME
538535
}
539536

@@ -688,7 +685,7 @@ func (es *ExecutionState) SetInitState(addr types.Address, transaction *types.Tr
688685
return nil
689686
}
690687

691-
func (es *ExecutionState) SlotInAccessList(addr types.Address, slot common.Hash) (addressOk bool, slotOk bool) {
688+
func (es *ExecutionState) SlotInAccessList(types.Address, common.Hash) (addressOk bool, slotOk bool) {
692689
return true, true // FIXME
693690
}
694691

@@ -1658,6 +1655,7 @@ func (es *ExecutionState) BuildBlock(blockId types.BlockNumber) (*BlockGeneratio
16581655
InTxnHashes: es.InTransactionHashes,
16591656
OutTxns: outTxnValues,
16601657
OutTxnHashes: outTxnHashes,
1658+
Receipts: es.Receipts,
16611659
ConfigParams: configParams,
16621660
}, nil
16631661
}
@@ -1979,16 +1977,11 @@ func (es *ExecutionState) resetVm() {
19791977
}
19801978

19811979
func (es *ExecutionState) MarshalJSON() ([]byte, error) {
1982-
prevBlockRes, err := es.shardAccessor.GetBlock().ByHash(es.PrevBlock)
1980+
prevBlock, err := es.shardAccessor.GetBlockHeaderByHash(es.PrevBlock)
19831981
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
19841982
return nil, err
19851983
}
19861984

1987-
var prevBlock *types.Block
1988-
if err == nil {
1989-
prevBlock = prevBlockRes.Block()
1990-
}
1991-
19921985
data := struct {
19931986
ContractTreeRoot common.Hash `json:"contractTreeRoot"`
19941987
ReceiptTreeRoot common.Hash `json:"receiptTreeRoot"`

0 commit comments

Comments
 (0)