Skip to content

Commit

Permalink
LedgerChangeReader: Support State Expiration & Eviction (#4941)
Browse files Browse the repository at this point in the history
* Simplify ScError.Equals

* Add missing case for ScVal.Equals

* Add LedgerEntry.SetContractData and LedgerEntry.SetContractCode methods

* update generated xdr to 0f5e556

* Add LedgerCloseMetaV2 support

* Update ledgerTransaction.GetOperationEvents

* Make LedgerChangeReader emit evictions

* Fixing up after merge

* Add test for LedgerChangeReader extensions and evictions

* Fix typo

* Add xdr.LedgerEntryData.ExpirationLedgerSeq helper

* review feedback
  • Loading branch information
Paul Bellamy authored Jul 3, 2023
1 parent 9313449 commit 8e85b8e
Show file tree
Hide file tree
Showing 5 changed files with 505 additions and 63 deletions.
40 changes: 40 additions & 0 deletions ingest/change.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ingest

import (
"bytes"
"fmt"

"github.com/stellar/go/support/errors"
"github.com/stellar/go/xdr"
Expand Down Expand Up @@ -68,6 +69,45 @@ func GetChangesFromLedgerEntryChanges(ledgerEntryChanges xdr.LedgerEntryChanges)
return changes
}

// GetChangesFromLedgerEntryEvictions transforms evicted LedgerKeys to []Change.
// The generated changes always remove the entries.
func GetChangesFromLedgerEntryEvictions(keys []xdr.LedgerKey) ([]Change, error) {
changes := []Change{}

for _, key := range keys {
state := xdr.LedgerEntry{}
switch key.Type {
case xdr.LedgerEntryTypeContractData:
err := state.Data.SetContractData(&xdr.ContractDataEntry{
Contract: key.ContractData.Contract,
Key: key.ContractData.Key,
Durability: key.ContractData.Durability,
})
if err != nil {
return nil, errors.Wrap(err, "error setting ContractDataEntry")
}
case xdr.LedgerEntryTypeContractCode:
err := state.Data.SetContractCode(&xdr.ContractCodeEntry{
Hash: key.ContractCode.Hash,
})
if err != nil {
return nil, errors.Wrap(err, "error setting ContractCodeEntry")
}
default:
// Currently only contractData and contractCode are evicted by core, so
// we only need to handle those two.
return nil, fmt.Errorf("invalid LedgerEntry eviction type: %s", key.Type)
}
changes = append(changes, Change{
Type: key.Type,
Pre: &state,
Post: nil,
})
}

return changes, nil
}

// LedgerEntryChangeType returns type in terms of LedgerEntryChangeType.
func (c *Change) LedgerEntryChangeType() xdr.LedgerEntryChangeType {
switch {
Expand Down
15 changes: 13 additions & 2 deletions ingest/ledger_change_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ type ledgerChangeReaderState int
const (
// feeChangesState is active when LedgerChangeReader is reading fee changes.
feeChangesState ledgerChangeReaderState = iota
// feeChangesState is active when LedgerChangeReader is reading transaction meta changes.
// metaChangesState is active when LedgerChangeReader is reading transaction meta changes.
metaChangesState
// feeChangesState is active when LedgerChangeReader is reading upgrade changes.
// evictionChangesState is active when LedgerChangeReader is reading ledger entry evictions.
evictionChangesState
// upgradeChanges is active when LedgerChangeReader is reading upgrade changes.
upgradeChangesState
)

Expand Down Expand Up @@ -122,6 +124,15 @@ func (r *LedgerChangeReader) Read() (Change, error) {
r.pending = append(r.pending, metaChanges...)
}
return r.Read()
case evictionChangesState:
// Get contract ledgerEntry evictions
changes, err := GetChangesFromLedgerEntryEvictions(r.ledgerCloseMeta.EvictedLedgerKeys())
if err != nil {
return Change{}, err
}
r.pending = append(r.pending, changes...)
r.state++
return r.Read()
case upgradeChangesState:
// Get upgrade changes
if r.upgradeIndex < len(r.LedgerTransactionReader.ledgerCloseMeta.UpgradesProcessing()) {
Expand Down
Loading

0 comments on commit 8e85b8e

Please sign in to comment.