From 7503026c1da3519c2e9e31177a0502426474a6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 27 Mar 2024 10:10:34 -0700 Subject: [PATCH] Revert "Optimise merge registers for migrations" --- .../migrations/account_storage_migration.go | 4 +- .../migrations/atree_register_migration.go | 8 +- .../migrations/cadence_value_validation.go | 2 +- .../migrations/cadence_values_migration.go | 4 +- .../cadence_values_migration_test.go | 8 +- cmd/util/ledger/migrations/merge.go | 72 ++++++ .../ledger/migrations/migrator_runtime.go | 4 +- .../migrations/transaction_migration.go | 6 +- cmd/util/ledger/util/payload_snapshot.go | 239 ------------------ cmd/util/ledger/util/payload_snapshot_test.go | 184 -------------- cmd/util/ledger/util/util.go | 43 +++- 11 files changed, 133 insertions(+), 441 deletions(-) create mode 100644 cmd/util/ledger/migrations/merge.go delete mode 100644 cmd/util/ledger/util/payload_snapshot.go delete mode 100644 cmd/util/ledger/util/payload_snapshot_test.go diff --git a/cmd/util/ledger/migrations/account_storage_migration.go b/cmd/util/ledger/migrations/account_storage_migration.go index 8bd2c527dfb..060d41cf168 100644 --- a/cmd/util/ledger/migrations/account_storage_migration.go +++ b/cmd/util/ledger/migrations/account_storage_migration.go @@ -58,9 +58,11 @@ func NewAccountStorageMigration( flow.Address(address): {}, } - newPayloads, err := migrationRuntime.Snapshot.ApplyChangesAndGetNewPayloads( + newPayloads, err := MergeRegisterChanges( + migrationRuntime.Snapshot.Payloads, result.WriteSet, expectedAddresses, + nil, log, ) if err != nil { diff --git a/cmd/util/ledger/migrations/atree_register_migration.go b/cmd/util/ledger/migrations/atree_register_migration.go index 0931fa61bcf..4de94d0fae4 100644 --- a/cmd/util/ledger/migrations/atree_register_migration.go +++ b/cmd/util/ledger/migrations/atree_register_migration.go @@ -129,7 +129,7 @@ func (m *AtreeRegisterMigrator) MigrateAccount( m.rw.Write(migrationProblem{ Address: address.Hex(), Key: "", - Size: mr.Snapshot.Len(), + Size: len(mr.Snapshot.Payloads), Kind: "more_registers_after_migration", Msg: fmt.Sprintf("original: %d, new: %d", originalLen, newLen), }) @@ -227,7 +227,7 @@ func (m *AtreeRegisterMigrator) convertStorageDomain( m.rw.Write(migrationProblem{ Address: mr.Address.Hex(), - Size: mr.Snapshot.Len(), + Size: len(mr.Snapshot.Payloads), Key: string(key), Kind: "migration_failure", Msg: err.Error(), @@ -245,7 +245,7 @@ func (m *AtreeRegisterMigrator) validateChangesAndCreateNewRegisters( storageMapIds map[string]struct{}, ) ([]*ledger.Payload, error) { originalPayloadsSnapshot := mr.Snapshot - originalPayloads := originalPayloadsSnapshot.PayloadMap() + originalPayloads := originalPayloadsSnapshot.Payloads newPayloads := make([]*ledger.Payload, 0, len(originalPayloads)) // store state payload so that it can be updated @@ -331,7 +331,7 @@ func (m *AtreeRegisterMigrator) validateChangesAndCreateNewRegisters( m.rw.Write(migrationProblem{ Address: mr.Address.Hex(), Key: id.String(), - Size: mr.Snapshot.Len(), + Size: len(mr.Snapshot.Payloads), Kind: "not_migrated", Msg: fmt.Sprintf("%x", value.Value()), }) diff --git a/cmd/util/ledger/migrations/cadence_value_validation.go b/cmd/util/ledger/migrations/cadence_value_validation.go index 6ec9435b9a3..e21183683dd 100644 --- a/cmd/util/ledger/migrations/cadence_value_validation.go +++ b/cmd/util/ledger/migrations/cadence_value_validation.go @@ -363,7 +363,7 @@ func newReadonlyStorageRuntime(payloads []*ledger.Payload) ( *readonlyStorageRuntime, error, ) { - snapshot, err := util.NewMapBasedPayloadSnapshot(payloads) + snapshot, err := util.NewPayloadSnapshot(payloads) if err != nil { return nil, fmt.Errorf("failed to create payload snapshot: %w", err) } diff --git a/cmd/util/ledger/migrations/cadence_values_migration.go b/cmd/util/ledger/migrations/cadence_values_migration.go index 6f0d4b63779..258852324e3 100644 --- a/cmd/util/ledger/migrations/cadence_values_migration.go +++ b/cmd/util/ledger/migrations/cadence_values_migration.go @@ -145,9 +145,11 @@ func (m *CadenceBaseMigrator) MigrateAccount( flow.Address(address): {}, } - newPayloads, err := migrationRuntime.Snapshot.ApplyChangesAndGetNewPayloads( + newPayloads, err := MergeRegisterChanges( + migrationRuntime.Snapshot.Payloads, result.WriteSet, expectedAddresses, + expectedAddresses, m.log, ) if err != nil { diff --git a/cmd/util/ledger/migrations/cadence_values_migration_test.go b/cmd/util/ledger/migrations/cadence_values_migration_test.go index 4a7afdb3c02..7e49507504f 100644 --- a/cmd/util/ledger/migrations/cadence_values_migration_test.go +++ b/cmd/util/ledger/migrations/cadence_values_migration_test.go @@ -796,9 +796,11 @@ func TestProgramParsingError(t *testing.T) { flow.Address(testAddress): {}, } - payloads, err = runtime.Snapshot.ApplyChangesAndGetNewPayloads( + payloads, err = MergeRegisterChanges( + runtime.Snapshot.Payloads, result.WriteSet, expectedAddresses, + nil, logger, ) require.NoError(t, err) @@ -932,9 +934,11 @@ func TestCoreContractUsage(t *testing.T) { flow.Address(testAddress): {}, } - payloads, err = runtime.Snapshot.ApplyChangesAndGetNewPayloads( + payloads, err = MergeRegisterChanges( + runtime.Snapshot.Payloads, result.WriteSet, expectedAddresses, + nil, logger, ) require.NoError(t, err) diff --git a/cmd/util/ledger/migrations/merge.go b/cmd/util/ledger/migrations/merge.go new file mode 100644 index 00000000000..81efe0a9fa5 --- /dev/null +++ b/cmd/util/ledger/migrations/merge.go @@ -0,0 +1,72 @@ +package migrations + +import ( + "github.com/rs/zerolog" + + "github.com/onflow/flow-go/ledger" + "github.com/onflow/flow-go/ledger/common/convert" + "github.com/onflow/flow-go/model/flow" +) + +func MergeRegisterChanges( + originalPayloads map[flow.RegisterID]*ledger.Payload, + changes map[flow.RegisterID]flow.RegisterValue, + expectedChangeAddresses map[flow.Address]struct{}, + expectedOriginalAddresses map[flow.Address]struct{}, + logger zerolog.Logger, +) ([]*ledger.Payload, error) { + + newPayloads := make([]*ledger.Payload, 0, len(originalPayloads)) + + // Add all new payloads. + for id, value := range changes { + delete(originalPayloads, id) + if len(value) == 0 { + continue + } + + if expectedChangeAddresses != nil { + ownerAddress := flow.BytesToAddress([]byte(id.Owner)) + + if _, ok := expectedChangeAddresses[ownerAddress]; !ok { + // something was changed that does not belong to this account. Log it. + logger.Error(). + Str("key", id.String()). + Str("actual_address", ownerAddress.Hex()). + Interface("expected_addresses", expectedChangeAddresses). + Hex("value", value). + Msg("key is part of the change set, but is for a different account") + } + } + + key := convert.RegisterIDToLedgerKey(id) + newPayloads = append(newPayloads, ledger.NewPayload(key, value)) + } + + // Add any old payload that wasn't updated. + for id, value := range originalPayloads { + if len(value.Value()) == 0 { + // This is strange, but we don't want to add empty values. Log it. + logger.Warn().Msgf("empty value for key %s", id) + continue + } + + if expectedOriginalAddresses != nil { + ownerAddress := flow.BytesToAddress([]byte(id.Owner)) + + if _, ok := expectedOriginalAddresses[ownerAddress]; !ok { + // something was changed that does not belong to this account. Log it. + logger.Error(). + Str("key", id.String()). + Str("actual_address", ownerAddress.Hex()). + Interface("expected_addresses", expectedOriginalAddresses). + Hex("value", value.Value()). + Msg("key is part of the original set, but is for a different account") + } + } + + newPayloads = append(newPayloads, value) + } + + return newPayloads, nil +} diff --git a/cmd/util/ledger/migrations/migrator_runtime.go b/cmd/util/ledger/migrations/migrator_runtime.go index 92da7ff36f0..074d0428d77 100644 --- a/cmd/util/ledger/migrations/migrator_runtime.go +++ b/cmd/util/ledger/migrations/migrator_runtime.go @@ -34,7 +34,7 @@ func NewMigratorRuntime( *migratorRuntime, error, ) { - snapshot, err := util.NewMapBasedPayloadSnapshot(payloads) + snapshot, err := util.NewPayloadSnapshot(payloads) if err != nil { return nil, fmt.Errorf("failed to create payload snapshot: %w", err) } @@ -107,7 +107,7 @@ func NewMigratorRuntime( } type migratorRuntime struct { - Snapshot util.MigrationStorageSnapshot + Snapshot *util.PayloadSnapshot TransactionState state.NestedTransactionPreparer Interpreter *interpreter.Interpreter Storage *runtime.Storage diff --git a/cmd/util/ledger/migrations/transaction_migration.go b/cmd/util/ledger/migrations/transaction_migration.go index 59e8d023e2c..16ad691c4ed 100644 --- a/cmd/util/ledger/migrations/transaction_migration.go +++ b/cmd/util/ledger/migrations/transaction_migration.go @@ -27,7 +27,7 @@ func NewTransactionBasedMigration( fvm.WithTransactionFeesEnabled(false)) ctx := fvm.NewContext(options...) - snapshot, err := util.NewMapBasedPayloadSnapshot(payloads) + snapshot, err := util.NewPayloadSnapshot(payloads) if err != nil { return nil, err } @@ -48,9 +48,11 @@ func NewTransactionBasedMigration( return nil, res.Err } - return snapshot.ApplyChangesAndGetNewPayloads( + return MergeRegisterChanges( + snapshot.Payloads, executionSnapshot.WriteSet, expectedWriteAddresses, + nil, logger, ) } diff --git a/cmd/util/ledger/util/payload_snapshot.go b/cmd/util/ledger/util/payload_snapshot.go deleted file mode 100644 index 59e3eca47f7..00000000000 --- a/cmd/util/ledger/util/payload_snapshot.go +++ /dev/null @@ -1,239 +0,0 @@ -package util - -import ( - "sort" - - "github.com/rs/zerolog" - - "github.com/onflow/flow-go/fvm/storage/snapshot" - "github.com/onflow/flow-go/ledger" - "github.com/onflow/flow-go/ledger/common/convert" - "github.com/onflow/flow-go/model/flow" -) - -type MigrationStorageSnapshot interface { - snapshot.StorageSnapshot - - Exists(id flow.RegisterID) bool - ApplyChangesAndGetNewPayloads( - changes map[flow.RegisterID]flow.RegisterValue, - expectedChangeAddresses map[flow.Address]struct{}, - logger zerolog.Logger, - ) ([]*ledger.Payload, error) - - Len() int - PayloadMap() map[flow.RegisterID]*ledger.Payload -} - -type PayloadSnapshot struct { - Payloads map[flow.RegisterID]*ledger.Payload -} - -var _ MigrationStorageSnapshot = PayloadSnapshot{} - -func NewPayloadSnapshot(payloads []*ledger.Payload) (*PayloadSnapshot, error) { - l := &PayloadSnapshot{ - Payloads: make(map[flow.RegisterID]*ledger.Payload, len(payloads)), - } - for _, payload := range payloads { - key, err := payload.Key() - if err != nil { - return nil, err - } - id, err := convert.LedgerKeyToRegisterID(key) - if err != nil { - return nil, err - } - l.Payloads[id] = payload - } - return l, nil -} - -func (p PayloadSnapshot) Get(id flow.RegisterID) (flow.RegisterValue, error) { - value, exists := p.Payloads[id] - if !exists { - return nil, nil - } - return value.Value(), nil -} - -func (p PayloadSnapshot) Exists(id flow.RegisterID) bool { - _, exists := p.Payloads[id] - return exists -} - -func (p PayloadSnapshot) Len() int { - return len(p.Payloads) -} - -func (p PayloadSnapshot) PayloadMap() map[flow.RegisterID]*ledger.Payload { - return p.Payloads -} - -// ApplyChangesAndGetNewPayloads applies the given changes to the snapshot and returns the new payloads. -// the snapshot is destroyed. -func (p PayloadSnapshot) ApplyChangesAndGetNewPayloads( - changes map[flow.RegisterID]flow.RegisterValue, - expectedChangeAddresses map[flow.Address]struct{}, - logger zerolog.Logger, -) ([]*ledger.Payload, error) { - originalPayloads := p.Payloads - - newPayloads := make([]*ledger.Payload, 0, len(originalPayloads)) - - // Add all new payloads. - for id, value := range changes { - delete(originalPayloads, id) - if len(value) == 0 { - continue - } - - if expectedChangeAddresses != nil { - ownerAddress := flow.BytesToAddress([]byte(id.Owner)) - - if _, ok := expectedChangeAddresses[ownerAddress]; !ok { - // something was changed that does not belong to this account. Log it. - logger.Error(). - Str("key", id.String()). - Str("actual_address", ownerAddress.Hex()). - Interface("expected_addresses", expectedChangeAddresses). - Hex("value", value). - Msg("key is part of the change set, but is for a different account") - } - } - - key := convert.RegisterIDToLedgerKey(id) - newPayloads = append(newPayloads, ledger.NewPayload(key, value)) - } - - // Add any old payload that wasn't updated. - for id, value := range originalPayloads { - if len(value.Value()) == 0 { - // This is strange, but we don't want to add empty values. Log it. - logger.Warn().Msgf("empty value for key %s", id) - continue - } - - newPayloads = append(newPayloads, value) - } - - return newPayloads, nil -} - -type MapBasedPayloadSnapshot struct { - reverseMap map[flow.RegisterID]int - payloads []*ledger.Payload -} - -var _ MigrationStorageSnapshot = (*MapBasedPayloadSnapshot)(nil) - -func NewMapBasedPayloadSnapshot(payloads []*ledger.Payload) (*MapBasedPayloadSnapshot, error) { - payloadsCopy := make([]*ledger.Payload, len(payloads)) - copy(payloadsCopy, payloads) - l := &MapBasedPayloadSnapshot{ - reverseMap: make(map[flow.RegisterID]int, len(payloads)), - payloads: payloadsCopy, - } - for i, payload := range payloadsCopy { - key, err := payload.Key() - if err != nil { - return nil, err - } - id, err := convert.LedgerKeyToRegisterID(key) - if err != nil { - return nil, err - } - l.reverseMap[id] = i - } - return l, nil -} - -func (p *MapBasedPayloadSnapshot) Get(id flow.RegisterID) (flow.RegisterValue, error) { - index, exists := p.reverseMap[id] - if !exists { - return nil, nil - } - return p.payloads[index].Value(), nil -} - -func (p *MapBasedPayloadSnapshot) Exists(id flow.RegisterID) bool { - _, exists := p.reverseMap[id] - return exists -} - -func (p *MapBasedPayloadSnapshot) Len() int { - return len(p.payloads) -} - -func (p *MapBasedPayloadSnapshot) PayloadMap() map[flow.RegisterID]*ledger.Payload { - result := make(map[flow.RegisterID]*ledger.Payload, len(p.payloads)) - for id, index := range p.reverseMap { - result[id] = p.payloads[index] - } - return result -} - -// ApplyChangesAndGetNewPayloads applies the given changes to the snapshot and returns the new payloads. -// the snapshot is destroyed. -func (p *MapBasedPayloadSnapshot) ApplyChangesAndGetNewPayloads( - changes map[flow.RegisterID]flow.RegisterValue, - expectedChangeAddresses map[flow.Address]struct{}, - logger zerolog.Logger, -) ([]*ledger.Payload, error) { - - // append all new payloads at once at the end - newPayloads := make([]*ledger.Payload, 0, len(changes)) - deletedPayloads := make([]int, 0, len(changes)) - - for id, value := range changes { - if expectedChangeAddresses != nil { - ownerAddress := flow.BytesToAddress([]byte(id.Owner)) - - if _, ok := expectedChangeAddresses[ownerAddress]; !ok { - // something was changed that does not belong to this account. Log it. - logger.Error(). - Str("key", id.String()). - Str("actual_address", ownerAddress.Hex()). - Interface("expected_addresses", expectedChangeAddresses). - Hex("value", value). - Msg("key is part of the change set, but is for a different account") - } - } - - existingItemIndex, exists := p.reverseMap[id] - if !exists { - if len(value) == 0 { - // do not add new empty values - continue - } - newPayloads = append(newPayloads, ledger.NewPayload(convert.RegisterIDToLedgerKey(id), value)) - } else { - if len(value) == 0 { - // do not add new empty values - deletedPayloads = append(deletedPayloads, existingItemIndex) - continue - } - - // update existing payload - p.payloads[existingItemIndex] = ledger.NewPayload(convert.RegisterIDToLedgerKey(id), value) - } - } - - // remove deleted payloads by moving the last ones to the deleted positions - // and then re-slicing the array - sort.Ints(deletedPayloads) - for i := len(deletedPayloads) - 1; i >= 0; i-- { - index := deletedPayloads[i] - // take items from the very end of the array - p.payloads[index] = p.payloads[len(p.payloads)-1-(len(deletedPayloads)-1-i)] - } - p.payloads = p.payloads[:len(p.payloads)-len(deletedPayloads)] - - result := append(p.payloads, newPayloads...) - - // destroy the snapshot to prevent further use - p.payloads = nil - p.reverseMap = nil - - return result, nil -} diff --git a/cmd/util/ledger/util/payload_snapshot_test.go b/cmd/util/ledger/util/payload_snapshot_test.go deleted file mode 100644 index 0b909e2af42..00000000000 --- a/cmd/util/ledger/util/payload_snapshot_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package util_test - -import ( - "crypto/rand" - "math/big" - "strconv" - "testing" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - - "github.com/onflow/flow-go/cmd/util/ledger/util" - "github.com/onflow/flow-go/ledger" - "github.com/onflow/flow-go/ledger/common/convert" - "github.com/onflow/flow-go/model/flow" -) - -func Benchmark_PayloadSnapshot(b *testing.B) { - benchMerge := func( - b *testing.B, - payloadsNum int, changesNum []int, - ) { - b.Run("merge_"+strconv.Itoa(payloadsNum), func(b *testing.B) { - benchmarkMerge(b, payloadsNum, changesNum) - }) - } - - benchCreate := func( - b *testing.B, - payloadsNum int, - ) { - b.Run("create_"+strconv.Itoa(payloadsNum), func(b *testing.B) { - benchmarkCreate(b, payloadsNum) - }) - } - - benchCreate(b, 1000) - benchCreate(b, 100000) - benchCreate(b, 10000000) - - benchMerge(b, 1000, []int{10, 100, 1000}) - benchMerge(b, 100000, []int{10, 1000, 100000}) - benchMerge(b, 10000000, []int{10, 10000, 10000000}) - -} - -func randomPayload(size int) []byte { - payload := make([]byte, size) - _, _ = rand.Read(payload) - return payload -} - -func randomInt(max int) int { - n, _ := rand.Int(rand.Reader, big.NewInt(int64(max))) - return int(n.Int64()) -} - -func createPayloads(payloadsNum int) []*ledger.Payload { - // 1kb payloads - payload := randomPayload(1024) - - payloads := make([]*ledger.Payload, payloadsNum) - for i := 0; i < payloadsNum; i++ { - p := make([]byte, len(payload)) - copy(p, payload) - payloads[i] = ledger.NewPayload( - convert.RegisterIDToLedgerKey(flow.RegisterID{ - Owner: flow.EmptyAddress.String(), - Key: strconv.Itoa(i), - }), - p, - ) - } - return payloads -} - -func benchmarkMerge(b *testing.B, payloadsNum int, changes []int) { - - creatChanges := func( - existingPayloadCount int, - changePayloads int, - deletePayloads int, - createPayloads int, - ) map[flow.RegisterID]flow.RegisterValue { - // half of the changes should be new payloads - changes := make(map[flow.RegisterID]flow.RegisterValue) - payload := randomPayload(1024) - for i := 0; i < changePayloads; i++ { - p := make([]byte, len(payload)) - copy(p, payload) - - // get random index - index := randomInt(existingPayloadCount) - - changes[flow.RegisterID{ - Owner: flow.EmptyAddress.String(), - Key: strconv.Itoa(index), - }] = p - } - - for i := 0; i < deletePayloads; i++ { - - // get random index - index := randomInt(existingPayloadCount) - - changes[flow.RegisterID{ - Owner: flow.EmptyAddress.String(), - Key: strconv.Itoa(index), - }] = []byte{} - } - - payload = randomPayload(1024) - for i := 0; i < createPayloads; i++ { - p := make([]byte, len(payload)) - copy(p, payload) - changes[flow.RegisterID{ - Owner: flow.EmptyAddress.String(), - Key: strconv.Itoa(i + existingPayloadCount), - }] = p - } - - return changes - } - - payloads := createPayloads(payloadsNum) - - for _, changesNum := range changes { - b.Run("changes_"+strconv.Itoa(changesNum), func(b *testing.B) { - - // third of the changes should be new payloads - // third of the changes should be existing payloads - // third of the changes should be removals - change, remove, add := changesNum/3, changesNum/3, changesNum-2*(changesNum/3) - - changes := creatChanges(len(payloads), change, remove, add) - - b.Run("MapBasedPayloadSnapshot", func(b *testing.B) { - for i := 0; i < b.N; i++ { - b.StopTimer() - snapshot, err := util.NewMapBasedPayloadSnapshot(payloads) - require.NoError(b, err) - b.StartTimer() - - _, err = snapshot.ApplyChangesAndGetNewPayloads(changes, nil, zerolog.Nop()) - require.NoError(b, err) - } - }) - - b.Run("PayloadSnapshot", func(b *testing.B) { - for i := 0; i < b.N; i++ { - b.StopTimer() - snapshot, err := util.NewPayloadSnapshot(payloads) - require.NoError(b, err) - b.StartTimer() - - _, err = snapshot.ApplyChangesAndGetNewPayloads(changes, nil, zerolog.Nop()) - require.NoError(b, err) - } - }) - }) - } -} - -func benchmarkCreate( - b *testing.B, - payloadsNum int, -) { - - payloads := createPayloads(payloadsNum) - - b.Run("MapBasedPayloadSnapshot", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := util.NewMapBasedPayloadSnapshot(payloads) - require.NoError(b, err) - } - }) - - b.Run("PayloadSnapshot", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := util.NewPayloadSnapshot(payloads) - require.NoError(b, err) - } - }) -} diff --git a/cmd/util/ledger/util/util.go b/cmd/util/ledger/util/util.go index c1da55fe6d9..b2248efb513 100644 --- a/cmd/util/ledger/util/util.go +++ b/cmd/util/ledger/util/util.go @@ -12,6 +12,7 @@ import ( "github.com/onflow/cadence/runtime/common" "github.com/onflow/flow-go/fvm/environment" + "github.com/onflow/flow-go/fvm/storage/snapshot" "github.com/onflow/flow-go/ledger" "github.com/onflow/flow-go/ledger/common/convert" "github.com/onflow/flow-go/model/flow" @@ -68,6 +69,38 @@ func (a *AccountsAtreeLedger) AllocateStorageIndex(owner []byte) (atree.StorageI return v, nil } +type PayloadSnapshot struct { + Payloads map[flow.RegisterID]*ledger.Payload +} + +var _ snapshot.StorageSnapshot = (*PayloadSnapshot)(nil) + +func NewPayloadSnapshot(payloads []*ledger.Payload) (*PayloadSnapshot, error) { + l := &PayloadSnapshot{ + Payloads: make(map[flow.RegisterID]*ledger.Payload, len(payloads)), + } + for _, payload := range payloads { + key, err := payload.Key() + if err != nil { + return nil, err + } + id, err := convert.LedgerKeyToRegisterID(key) + if err != nil { + return nil, err + } + l.Payloads[id] = payload + } + return l, nil +} + +func (p PayloadSnapshot) Get(id flow.RegisterID) (flow.RegisterValue, error) { + value, exists := p.Payloads[id] + if !exists { + return nil, nil + } + return value.Value(), nil +} + // NopMemoryGauge is a no-op implementation of the MemoryGauge interface type NopMemoryGauge struct{} @@ -78,7 +111,7 @@ func (n NopMemoryGauge) MeterMemory(common.MemoryUsage) error { var _ common.MemoryGauge = (*NopMemoryGauge)(nil) type PayloadsReadonlyLedger struct { - Snapshot MigrationStorageSnapshot + Snapshot *PayloadSnapshot AllocateStorageIndexFunc func(owner []byte) (atree.StorageIndex, error) SetValueFunc func(owner, key, value []byte) (err error) @@ -100,9 +133,9 @@ func (p *PayloadsReadonlyLedger) SetValue(owner, key, value []byte) (err error) panic("SetValue not expected to be called") } -func (p *PayloadsReadonlyLedger) ValueExists(owner, key []byte) (bool, error) { - exists := p.Snapshot.Exists(flow.NewRegisterID(flow.BytesToAddress(owner), string(key))) - return exists, nil +func (p *PayloadsReadonlyLedger) ValueExists(owner, key []byte) (exists bool, err error) { + _, ok := p.Snapshot.Payloads[flow.NewRegisterID(flow.BytesToAddress(owner), string(key))] + return ok, nil } func (p *PayloadsReadonlyLedger) AllocateStorageIndex(owner []byte) (atree.StorageIndex, error) { @@ -113,7 +146,7 @@ func (p *PayloadsReadonlyLedger) AllocateStorageIndex(owner []byte) (atree.Stora panic("AllocateStorageIndex not expected to be called") } -func NewPayloadsReadonlyLedger(snapshot MigrationStorageSnapshot) *PayloadsReadonlyLedger { +func NewPayloadsReadonlyLedger(snapshot *PayloadSnapshot) *PayloadsReadonlyLedger { return &PayloadsReadonlyLedger{Snapshot: snapshot} }