Skip to content

Commit 411ba8a

Browse files
committed
migration impl
Signed-off-by: Joshua Kim <[email protected]>
1 parent a52c1e4 commit 411ba8a

File tree

8 files changed

+552
-35
lines changed

8 files changed

+552
-35
lines changed

vms/avm/block/executor/block.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func (b *Block) Verify(context.Context) error {
201201
return nil
202202
}
203203

204-
func (b *Block) Accept(context.Context) error {
204+
func (b *Block) Accept(ctx context.Context) error {
205205
blkID := b.ID()
206206
defer b.manager.free(blkID)
207207

@@ -246,7 +246,7 @@ func (b *Block) Accept(context.Context) error {
246246
return err
247247
}
248248

249-
txChecksum, utxoChecksum := b.manager.state.Checksums()
249+
txChecksum, utxoChecksum := b.manager.state.Checksums(ctx)
250250
b.manager.backend.Ctx.Log.Trace(
251251
"accepted block",
252252
zap.Stringer("blkID", blkID),

vms/avm/state/state.go

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
package state
55

66
import (
7+
"context"
78
"errors"
89
"fmt"
10+
"iter"
911
"time"
1012

1113
"github.com/prometheus/client_golang/prometheus"
@@ -29,6 +31,7 @@ const (
2931

3032
var (
3133
utxoPrefix = []byte("utxo")
34+
indexPrefix = []byte("index")
3235
txPrefix = []byte("tx")
3336
blockIDPrefix = []byte("blockID")
3437
blockPrefix = []byte("block")
@@ -90,7 +93,11 @@ type State interface {
9093
CommitBatch() (database.Batch, error)
9194

9295
// Checksums returns the current TxChecksum and UTXOChecksum.
93-
Checksums() (txChecksum ids.ID, utxoChecksum ids.ID)
96+
Checksums(ctx context.Context) (txChecksum ids.ID, utxoChecksum ids.ID, err error)
97+
98+
UTXOs() iter.Seq2[*avax.UTXO, error]
99+
Txs() iter.Seq2[*txs.Tx, error]
100+
Blocks() iter.Seq2[block.Block, error]
94101

95102
Close() error
96103
}
@@ -150,7 +157,30 @@ func New(
150157
blockIDDB := prefixdb.New(blockIDPrefix, db)
151158
blockDB := prefixdb.New(blockPrefix, db)
152159
singletonDB := prefixdb.New(singletonPrefix, db)
160+
return newWithDatabases(
161+
db,
162+
utxoDB,
163+
txDB,
164+
blockIDDB,
165+
blockDB,
166+
singletonDB,
167+
parser,
168+
metrics,
169+
trackChecksums,
170+
)
171+
}
153172

173+
func newWithDatabases(
174+
db *versiondb.Database,
175+
utxoDB database.Database,
176+
txDB database.Database,
177+
blockIDDB database.Database,
178+
blockDB database.Database,
179+
singletonDB database.Database,
180+
parser block.Parser,
181+
metrics prometheus.Registerer,
182+
trackChecksums bool,
183+
) (*state, error) {
154184
txCache, err := metercacher.New[ids.ID, *txs.Tx](
155185
"tx_cache",
156186
metrics,
@@ -178,7 +208,13 @@ func New(
178208
return nil, err
179209
}
180210

181-
utxoState, err := avax.NewMeteredUTXOState(utxoDB, parser.Codec(), metrics, trackChecksums)
211+
utxoState, err := avax.NewMeteredUTXOState(
212+
prefixdb.New(utxoPrefix, utxoDB),
213+
prefixdb.New(indexPrefix, utxoDB),
214+
parser.Codec(),
215+
metrics,
216+
trackChecksums,
217+
)
182218
if err != nil {
183219
return nil, err
184220
}
@@ -407,6 +443,46 @@ func (s *state) CommitBatch() (database.Batch, error) {
407443
return s.db.CommitBatch()
408444
}
409445

446+
func (s *state) UTXOs() iter.Seq2[*avax.UTXO, error] {
447+
return s.utxoState.UTXOs()
448+
}
449+
450+
func (s *state) Txs() iter.Seq2[*txs.Tx, error] {
451+
return func(yield func(*txs.Tx, error) bool) {
452+
itr := s.txDB.NewIterator()
453+
defer itr.Release()
454+
455+
for itr.Next() {
456+
tx, err := s.parser.ParseGenesisTx(itr.Value())
457+
if err != nil {
458+
return
459+
}
460+
461+
if !yield(tx, errors.Join(err, itr.Error())) {
462+
return
463+
}
464+
}
465+
}
466+
}
467+
468+
func (s *state) Blocks() iter.Seq2[block.Block, error] {
469+
return func(yield func(block.Block, error) bool) {
470+
itr := s.blockDB.NewIterator()
471+
defer itr.Release()
472+
473+
for itr.Next() {
474+
blk, err := s.parser.ParseBlock(itr.Value())
475+
if err != nil {
476+
return
477+
}
478+
479+
if !yield(blk, errors.Join(err, itr.Error())) {
480+
return
481+
}
482+
}
483+
}
484+
}
485+
410486
func (s *state) Close() error {
411487
return errors.Join(
412488
s.utxoDB.Close(),
@@ -500,8 +576,8 @@ func (s *state) writeMetadata() error {
500576
return nil
501577
}
502578

503-
func (s *state) Checksums() (ids.ID, ids.ID) {
504-
return s.txChecksum, s.utxoState.Checksum()
579+
func (s *state) Checksums(context.Context) (ids.ID, ids.ID, error) {
580+
return s.txChecksum, s.utxoState.Checksum(), nil
505581
}
506582

507583
func (s *state) initTxChecksum() error {

vms/avm/state/state_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@
44
package state
55

66
import (
7+
"context"
8+
"fmt"
79
"testing"
810
"time"
911

12+
"github.com/google/go-cmp/cmp/cmpopts"
1013
"github.com/prometheus/client_golang/prometheus"
1114
"github.com/stretchr/testify/require"
15+
"gotest.tools/v3/assert/cmp"
1216

1317
"github.com/ava-labs/avalanchego/database"
1418
"github.com/ava-labs/avalanchego/database/memdb"
1519
"github.com/ava-labs/avalanchego/database/versiondb"
1620
"github.com/ava-labs/avalanchego/ids"
1721
"github.com/ava-labs/avalanchego/upgrade"
22+
"github.com/ava-labs/avalanchego/utils/logging"
1823
"github.com/ava-labs/avalanchego/vms/avm/block"
1924
"github.com/ava-labs/avalanchego/vms/avm/fxs"
2025
"github.com/ava-labs/avalanchego/vms/avm/txs"
@@ -316,3 +321,69 @@ func TestInitializeChainState(t *testing.T) {
316321
require.NoError(err)
317322
require.Equal(genesis.ID(), lastAccepted.Parent())
318323
}
324+
325+
func TestStateMigration(t *testing.T) {
326+
require := require.New(t)
327+
328+
prev, err := New(
329+
versiondb.New(memdb.New()),
330+
parser,
331+
prometheus.NewRegistry(),
332+
false,
333+
)
334+
require.NoError(err)
335+
336+
prev.AddUTXO(populatedUTXO)
337+
prev.AddTx(populatedTx)
338+
prev.AddBlock(populatedBlk)
339+
require.NoError(prev.Commit())
340+
341+
next, err := NewStateV2(
342+
context.Background(),
343+
versiondb.New(memdb.New()),
344+
parser,
345+
prometheus.NewRegistry(),
346+
false,
347+
)
348+
require.NoError(err)
349+
350+
require.NoError(Migrate(logging.NoLog{}, prev, next))
351+
352+
gotUTXO, err := next.GetUTXO(populatedUTXOID)
353+
require.NoError(err)
354+
c := cmp.DeepEqual(
355+
populatedUTXO,
356+
gotUTXO,
357+
cmpopts.EquateEmpty(),
358+
cmpopts.IgnoreUnexported(avax.UTXOID{}, secp256k1fx.OutputOwners{}),
359+
)()
360+
require.Truef(c.Success(), fmt.Sprintf("%s", c))
361+
362+
gotTx, err := next.GetTx(populatedTxID)
363+
require.NoError(err)
364+
c = cmp.DeepEqual(
365+
populatedTx,
366+
gotTx,
367+
cmpopts.EquateEmpty(),
368+
cmpopts.IgnoreUnexported(txs.Tx{}, txs.BaseTx{}),
369+
)()
370+
require.Truef(c.Success(), fmt.Sprintf("%s", c))
371+
372+
gotBlk, err := next.GetBlock(populatedBlkID)
373+
require.NoError(err)
374+
c = cmp.DeepEqual(
375+
populatedBlk,
376+
gotBlk,
377+
cmpopts.EquateEmpty(),
378+
cmpopts.IgnoreUnexported(block.StandardBlock{}, txs.Tx{}, txs.BaseTx{}),
379+
)()
380+
require.Truef(c.Success(), fmt.Sprintf("%s", c))
381+
382+
gotBlkID, err := next.GetBlockIDAtHeight(populatedBlkHeight)
383+
require.NoError(err)
384+
require.Equal(populatedBlkID, gotBlkID)
385+
386+
require.Equal(prev.GetLastAccepted(), next.GetLastAccepted())
387+
require.Equal(prev.GetTimestamp(), next.GetTimestamp())
388+
require.True(next.IsInitialized())
389+
}

0 commit comments

Comments
 (0)