Skip to content

Commit

Permalink
Decouple tstate from merkledb
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronbuchwald committed Jan 15, 2025
1 parent 143eaea commit 7ed4d5a
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 76 deletions.
4 changes: 2 additions & 2 deletions chain/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,8 @@ func (c *Builder) BuildBlock(ctx context.Context, parentView state.View, parent
return nil, nil, nil, err
}

// Get view from [tstate] after writing all changed keys
view, err := ts.ExportMerkleDBView(ctx, c.tracer, parentView)
// Calculate new view from parent and state diff
view, err := createView(ctx, c.tracer, parentView, ts.ChangedKeys())
if err != nil {
return nil, nil, nil, err
}
Expand Down
22 changes: 21 additions & 1 deletion chain/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/trace"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/maybe"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/x/merkledb"
"go.opentelemetry.io/otel/attribute"
"go.uber.org/zap"

"github.com/ava-labs/hypersdk/internal/executor"
Expand All @@ -23,6 +25,8 @@ import (
"github.com/ava-labs/hypersdk/internal/workers"
"github.com/ava-labs/hypersdk/state"
"github.com/ava-labs/hypersdk/state/tstate"

oteltrace "go.opentelemetry.io/otel/trace"
)

type ExecutionBlock struct {
Expand Down Expand Up @@ -242,7 +246,8 @@ func (p *Processor) Execute(
// Get view from [tstate] after processing all state transitions
p.metrics.stateChanges.Add(float64(ts.PendingChanges()))
p.metrics.stateOperations.Add(float64(ts.OpIndex()))
view, err := ts.ExportMerkleDBView(ctx, p.tracer, parentView)

view, err := createView(ctx, p.tracer, parentView, ts.ChangedKeys())
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -409,3 +414,18 @@ func (p *Processor) AsyncVerify(ctx context.Context, block *ExecutionBlock) erro
}
return nil
}

func createView(ctx context.Context, tracer trace.Tracer, parentView state.View, stateDiff map[string]maybe.Maybe[[]byte]) (merkledb.View, error) {
ctx, span := tracer.Start(
ctx, "Chain.CreateView",
oteltrace.WithAttributes(
attribute.Int("items", len(stateDiff)),
),
)
defer span.End()

return parentView.NewView(ctx, merkledb.ViewChanges{
MapOps: stateDiff,
ConsumeBytes: true,
})
}
16 changes: 0 additions & 16 deletions state/tstate/dependencies.go

This file was deleted.

25 changes: 2 additions & 23 deletions state/tstate/tstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ import (
"context"
"sync"

"github.com/ava-labs/avalanchego/trace"
"github.com/ava-labs/avalanchego/utils/maybe"
"github.com/ava-labs/avalanchego/x/merkledb"
"go.opentelemetry.io/otel/attribute"

"github.com/ava-labs/hypersdk/state"

oteltrace "go.opentelemetry.io/otel/trace"
)

// TState defines a struct for storing temporary state.
Expand Down Expand Up @@ -60,23 +53,9 @@ func (ts *TState) OpIndex() int {
return ts.ops
}

// ExportMerkleDBView creates a slice of [database.BatchOp] of all
// changes in [TState] that can be used to commit to [merkledb].
func (ts *TState) ExportMerkleDBView(
ctx context.Context,
t trace.Tracer, //nolint:interfacer
view state.View,
) (merkledb.View, error) {
func (ts *TState) ChangedKeys() map[string]maybe.Maybe[[]byte] {
ts.l.RLock()
defer ts.l.RUnlock()

ctx, span := t.Start(
ctx, "TState.ExportMerkleDBView",
oteltrace.WithAttributes(
attribute.Int("items", len(ts.changedKeys)),
),
)
defer span.End()

return view.NewView(ctx, merkledb.ViewChanges{MapOps: ts.changedKeys, ConsumeBytes: true})
return ts.changedKeys
}
42 changes: 11 additions & 31 deletions state/tstate/tstate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import (
"testing"

"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/database/memdb"
"github.com/ava-labs/avalanchego/utils/maybe"
"github.com/ava-labs/avalanchego/utils/units"
"github.com/ava-labs/avalanchego/x/merkledb"
"github.com/stretchr/testify/require"

"github.com/ava-labs/hypersdk/internal/trace"
"github.com/ava-labs/hypersdk/keys"
"github.com/ava-labs/hypersdk/state"
)
Expand Down Expand Up @@ -576,19 +572,6 @@ func TestCreateView(t *testing.T) {

ctx := context.TODO()
ts := New(10)
tracer, err := trace.New(&trace.Config{Enabled: false})
require.NoError(err)
db, err := merkledb.New(ctx, memdb.New(), merkledb.Config{
BranchFactor: merkledb.BranchFactor16,
RootGenConcurrency: 1,
HistoryLength: 100,
ValueNodeCacheSize: units.MiB,
IntermediateNodeCacheSize: units.MiB,
IntermediateWriteBufferSize: units.KiB,
IntermediateWriteBatchSize: units.KiB,
Tracer: tracer,
})
require.NoError(err)
keys := [][]byte{key1, key2, key3}
keySet := state.Keys{
key1str: state.All,
Expand Down Expand Up @@ -629,15 +612,13 @@ func TestCreateView(t *testing.T) {
require.Empty(allocates)
require.Equal(map[string]uint16{key1str: 1}, writes)

// Create merkle view
view, err := ts.ExportMerkleDBView(ctx, tracer, db)
require.NoError(err, "error writing changes")
require.NoError(view.CommitToDB(ctx))

// Check if db was updated correctly
// Extract state diff
stateDiff := ts.ChangedKeys()
// Check if diff includes the correct keys
for i, key := range keys {
val, _ := db.GetValue(ctx, key)
require.Equal(vals[i], val, "value not updated in db")
maybeValue := stateDiff[string(key)]
require.True(maybeValue.HasValue())
require.Equal(vals[i], maybeValue.Value())
}

// Remove
Expand All @@ -660,14 +641,13 @@ func TestCreateView(t *testing.T) {
tsv.Commit()

// Create merkle view
view, err = tsv.ts.ExportMerkleDBView(ctx, tracer, db)
require.NoError(err, "error writing changes")
require.NoError(view.CommitToDB(ctx))
stateDiff = ts.ChangedKeys()

// Check if db was updated correctly
// Check if state diff was updated correctly
for _, key := range keys {
_, err := db.GetValue(ctx, key)
require.ErrorIs(err, database.ErrNotFound, "value not removed from db")
maybeValue := stateDiff[string(key)]
require.NotNil(maybeValue)
require.False(maybeValue.HasValue())
}
}

Expand Down
5 changes: 2 additions & 3 deletions vm/resolutions.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/ava-labs/hypersdk/internal/validitywindow"
"github.com/ava-labs/hypersdk/internal/workers"
"github.com/ava-labs/hypersdk/state"
"github.com/ava-labs/hypersdk/state/tstate"

internalfees "github.com/ava-labs/hypersdk/internal/fees"
)
Expand Down Expand Up @@ -120,12 +119,12 @@ func (vm *VM) State() (merkledb.MerkleDB, error) {
}

func (vm *VM) ImmutableState(ctx context.Context) (state.Immutable, error) {
ts := tstate.New(0)
state, err := vm.State()
if err != nil {
return nil, err
}
return ts.ExportMerkleDBView(ctx, vm.tracer, state)

return state.NewView(ctx, merkledb.ViewChanges{MapOps: nil, ConsumeBytes: true})
}

func (vm *VM) Mempool() chain.Mempool {
Expand Down

0 comments on commit 7ed4d5a

Please sign in to comment.