diff --git a/state/aggregator22.go b/state/aggregator22.go index 1f21b1769..a19f4d70d 100644 --- a/state/aggregator22.go +++ b/state/aggregator22.go @@ -742,10 +742,25 @@ func (ac *Aggregator22Context) IsMaxCodeTxNum(addr []byte, txNum uint64) bool { return ac.code.IsMaxTxNum(addr, txNum) } +func (ac *Aggregator22Context) ReadAccountDataNoStateWithRecent(addr []byte, txNum uint64) ([]byte, bool, error) { + return ac.accounts.GetNoStateWithRecent(addr, txNum, ac.tx) +} + func (ac *Aggregator22Context) ReadAccountDataNoState(addr []byte, txNum uint64) ([]byte, bool, error) { return ac.accounts.GetNoState(addr, txNum) } +func (ac *Aggregator22Context) ReadAccountStorageNoStateWithRecent(addr []byte, loc []byte, txNum uint64) ([]byte, bool, error) { + if cap(ac.keyBuf) < len(addr)+len(loc) { + ac.keyBuf = make([]byte, len(addr)+len(loc)) + } else if len(ac.keyBuf) != len(addr)+len(loc) { + ac.keyBuf = ac.keyBuf[:len(addr)+len(loc)] + } + copy(ac.keyBuf, addr) + copy(ac.keyBuf[len(addr):], loc) + return ac.storage.GetNoStateWithRecent(ac.keyBuf, txNum, ac.tx) +} + func (ac *Aggregator22Context) ReadAccountStorageNoState(addr []byte, loc []byte, txNum uint64) ([]byte, bool, error) { if cap(ac.keyBuf) < len(addr)+len(loc) { ac.keyBuf = make([]byte, len(addr)+len(loc)) @@ -757,10 +772,20 @@ func (ac *Aggregator22Context) ReadAccountStorageNoState(addr []byte, loc []byte return ac.storage.GetNoState(ac.keyBuf, txNum) } +func (ac *Aggregator22Context) ReadAccountCodeNoStateWithRecent(addr []byte, txNum uint64) ([]byte, bool, error) { + return ac.code.GetNoStateWithRecent(addr, txNum, ac.tx) +} func (ac *Aggregator22Context) ReadAccountCodeNoState(addr []byte, txNum uint64) ([]byte, bool, error) { return ac.code.GetNoState(addr, txNum) } +func (ac *Aggregator22Context) ReadAccountCodeSizeNoStateWithRecent(addr []byte, txNum uint64) (int, bool, error) { + code, noState, err := ac.code.GetNoStateWithRecent(addr, txNum, ac.tx) + if err != nil { + return 0, false, err + } + return len(code), noState, nil +} func (ac *Aggregator22Context) ReadAccountCodeSizeNoState(addr []byte, txNum uint64) (int, bool, error) { code, noState, err := ac.code.GetNoState(addr, txNum) if err != nil { @@ -815,6 +840,8 @@ type Aggregator22Context struct { logTopics *InvertedIndexContext tracesFrom *InvertedIndexContext tracesTo *InvertedIndexContext + + tx kv.Tx } func (a *Aggregator22) MakeContext() *Aggregator22Context { @@ -829,3 +856,4 @@ func (a *Aggregator22) MakeContext() *Aggregator22Context { tracesTo: a.tracesTo.MakeContext(), } } +func (ac *Aggregator22Context) SetTx(tx kv.Tx) { ac.tx = tx } diff --git a/state/history.go b/state/history.go index ceae1af68..ced2b35f4 100644 --- a/state/history.go +++ b/state/history.go @@ -597,6 +597,8 @@ func (h *History) pruneF(txFrom, txTo uint64, f func(txNum uint64, k, v []byte) type HistoryContext struct { h *History indexFiles, historyFiles *btree.BTreeG[*ctxItem] + + tx kv.Tx } func (h *History) MakeContext() *HistoryContext { @@ -623,6 +625,47 @@ func (h *History) MakeContext() *HistoryContext { }) return &hc } +func (hc *HistoryContext) SetTx(tx kv.Tx) { hc.tx = tx } + +func (hc *HistoryContext) getNoStateFromDB(key []byte, txNum uint64, tx kv.Tx) ([]byte, bool, error) { + var txKey [8]byte + binary.BigEndian.PutUint64(txKey[:], txNum) + historyKeysCursor, err := tx.CursorDupSort(hc.h.indexKeysTable) + if err != nil { + return nil, false, fmt.Errorf("create %s history cursor: %w", hc.h.filenameBase, err) + } + defer historyKeysCursor.Close() + valsC, err := tx.Cursor(hc.h.historyValsTable) + if err != nil { + return nil, false, err + } + defer valsC.Close() + v, err := historyKeysCursor.SeekBothRange(txKey[:], key) + if err != nil { + return nil, false, err + } + if len(v) > 0 { + key2, txnNumBytes := v[:len(v)-8], v[len(v)-8:] + _ = key2 + _, vv, err := valsC.SeekExact(txnNumBytes) + if err != nil { + return nil, false, err + } + return vv, vv != nil, nil + } + return nil, false, nil +} + +func (hc *HistoryContext) GetNoStateWithRecent(key []byte, txNum uint64, tx kv.Tx) ([]byte, bool, error) { + enc, ok, err := hc.getNoStateFromDB(key, txNum, tx) + if err != nil { + return nil, false, err + } + if ok { + return enc, true, nil + } + return hc.GetNoState(key, txNum) +} func (hc *HistoryContext) GetNoState(key []byte, txNum uint64) ([]byte, bool, error) { //fmt.Printf("GetNoState [%x] %d\n", key, txNum)