Skip to content

Commit fb34278

Browse files
committed
firewood x-chain
Signed-off-by: Joshua Kim <20001595+joshua-kim@users.noreply.github.com>
1 parent b3857f9 commit fb34278

File tree

28 files changed

+1626
-187
lines changed

28 files changed

+1626
-187
lines changed

database/memdb/db.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package memdb
55

66
import (
77
"context"
8+
"fmt"
89
"slices"
910
"strings"
1011
"sync"
@@ -38,6 +39,21 @@ func New() *Database {
3839
return NewWithSize(DefaultSize)
3940
}
4041

42+
// Copy returns a Database with the same key-value pairs as db
43+
func Copy(db *Database) (*Database, error) {
44+
db.lock.Lock()
45+
defer db.lock.Unlock()
46+
47+
result := New()
48+
for k, v := range db.db {
49+
if err := result.Put([]byte(k), v); err != nil {
50+
return nil, fmt.Errorf("failed to insert key: %w", err)
51+
}
52+
}
53+
54+
return result, nil
55+
}
56+
4157
// NewWithSize returns a map pre-allocated to the provided size with the
4258
// Database interface methods implemented.
4359
func NewWithSize(size int) *Database {

vms/avm/block/builder/builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,5 +174,5 @@ func (b *builder) BuildBlock(context.Context) (snowman.Block, error) {
174174
return nil, err
175175
}
176176

177-
return b.manager.NewBlock(statelessBlk), nil
177+
return b.manager.NewBlock(statelessBlk, b.backend.Ctx.SharedMemory), nil
178178
}

vms/avm/block/builder/builder_test.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/stretchr/testify/require"
1313
"go.uber.org/mock/gomock"
1414

15+
"github.com/ava-labs/avalanchego/chains/atomic"
1516
"github.com/ava-labs/avalanchego/codec"
1617
"github.com/ava-labs/avalanchego/codec/codecmock"
1718
"github.com/ava-labs/avalanchego/database/memdb"
@@ -291,8 +292,11 @@ func TestBuilderBuildBlock(t *testing.T) {
291292
manager.EXPECT().VerifyUniqueInputs(preferredID, gomock.Any()).Return(nil)
292293
// Assert created block has one tx, tx1,
293294
// and other fields are set correctly.
294-
manager.EXPECT().NewBlock(gomock.Any()).DoAndReturn(
295-
func(block *block.StandardBlock) snowman.Block {
295+
manager.EXPECT().NewBlock(gomock.Any(), gomock.Any()).DoAndReturn(
296+
func(
297+
block *block.StandardBlock,
298+
_ atomic.SharedMemory,
299+
) snowman.Block {
296300
require.Len(t, block.Transactions, 1)
297301
require.Equal(t, tx1, block.Transactions[0])
298302
require.Equal(t, preferredHeight+1, block.Height())
@@ -350,8 +354,11 @@ func TestBuilderBuildBlock(t *testing.T) {
350354
manager.EXPECT().GetState(preferredID).Return(preferredState, true)
351355
manager.EXPECT().VerifyUniqueInputs(preferredID, gomock.Any()).Return(nil)
352356
// Assert that the created block has the right timestamp
353-
manager.EXPECT().NewBlock(gomock.Any()).DoAndReturn(
354-
func(block *block.StandardBlock) snowman.Block {
357+
manager.EXPECT().NewBlock(gomock.Any(), gomock.Any()).DoAndReturn(
358+
func(
359+
block *block.StandardBlock,
360+
_ atomic.SharedMemory,
361+
) snowman.Block {
355362
require.Equal(t, preferredTimestamp.Unix(), block.Timestamp().Unix())
356363
return nil
357364
},
@@ -422,8 +429,11 @@ func TestBuilderBuildBlock(t *testing.T) {
422429
manager.EXPECT().GetState(preferredID).Return(preferredState, true)
423430
manager.EXPECT().VerifyUniqueInputs(preferredID, gomock.Any()).Return(nil)
424431
// Assert that the created block has the right timestamp
425-
manager.EXPECT().NewBlock(gomock.Any()).DoAndReturn(
426-
func(block *block.StandardBlock) snowman.Block {
432+
manager.EXPECT().NewBlock(gomock.Any(), gomock.Any()).DoAndReturn(
433+
func(
434+
block *block.StandardBlock,
435+
_ atomic.SharedMemory,
436+
) snowman.Block {
427437
require.Equal(t, now.Unix(), block.Timestamp().Unix())
428438
return nil
429439
},
@@ -526,7 +536,7 @@ func TestBlockBuilderAddLocalTx(t *testing.T) {
526536
parentBlk, err := block.NewStandardBlock(parentID, 0, parentTimestamp, txs, cm)
527537
require.NoError(err)
528538
state.AddBlock(parentBlk)
529-
state.SetLastAccepted(parentBlk.ID())
539+
state.SetLastAccepted(parentBlk.ID(), parentBlk.Height())
530540

531541
metrics, err := metrics.New(registerer)
532542
require.NoError(err)

vms/avm/block/executor/block.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ var (
3636
// Exported for testing in avm package.
3737
type Block struct {
3838
block.Block
39-
manager *manager
39+
manager *manager
40+
sharedMemory atomic.SharedMemory
4041
}
4142

4243
func (b *Block) Verify(context.Context) error {
@@ -201,15 +202,15 @@ func (b *Block) Verify(context.Context) error {
201202

202203
// Now that the block has been executed, we can add the block data to the
203204
// state diff.
204-
stateDiff.SetLastAccepted(blkID)
205+
stateDiff.SetLastAccepted(blkID, b.Height())
205206
stateDiff.AddBlock(b.Block)
206207

207208
b.manager.blkIDToState[blkID] = blockState
208209
b.manager.mempool.Remove(txs...)
209210
return nil
210211
}
211212

212-
func (b *Block) Accept(context.Context) error {
213+
func (b *Block) Accept(ctx context.Context) error {
213214
blkID := b.ID()
214215
defer b.manager.free(blkID)
215216

@@ -240,20 +241,25 @@ func (b *Block) Accept(context.Context) error {
240241
}
241242

242243
// Note that this method writes [batch] to the database.
243-
if err := b.manager.backend.Ctx.SharedMemory.Apply(blkState.atomicRequests, batch); err != nil {
244+
if err := b.sharedMemory.Apply(blkState.atomicRequests, batch); err != nil {
244245
return fmt.Errorf("failed to apply state diff to shared memory: %w", err)
245246
}
246247

247248
if err := b.manager.metrics.MarkBlockAccepted(b); err != nil {
248249
return err
249250
}
250251

252+
checksum, err := b.manager.state.Checksum(ctx)
253+
if err != nil {
254+
return fmt.Errorf("failed to get checksum: %w", err)
255+
}
256+
251257
b.manager.backend.Ctx.Log.Trace(
252258
"accepted block",
253259
zap.Stringer("blkID", blkID),
254260
zap.Uint64("height", b.Height()),
255261
zap.Stringer("parentID", b.Parent()),
256-
zap.Stringer("checksum", b.manager.state.Checksum()),
262+
zap.Stringer("checksum", checksum),
257263
)
258264
return nil
259265
}

vms/avm/block/executor/block_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ func TestBlockAccept(t *testing.T) {
683683
},
684684
},
685685
},
686+
sharedMemory: mockSharedMemory,
686687
}
687688
},
688689
expectedErr: errTest,
@@ -726,6 +727,7 @@ func TestBlockAccept(t *testing.T) {
726727
},
727728
},
728729
},
730+
sharedMemory: mockSharedMemory,
729731
}
730732
},
731733
expectedErr: errTest,
@@ -748,7 +750,7 @@ func TestBlockAccept(t *testing.T) {
748750
// because we mock the call to shared memory
749751
mockManagerState.EXPECT().CommitBatch().Return(nil, nil)
750752
mockManagerState.EXPECT().Abort()
751-
mockManagerState.EXPECT().Checksum().Return(ids.Empty)
753+
mockManagerState.EXPECT().Checksum(gomock.Any()).Return(ids.Empty, nil)
752754

753755
mockSharedMemory := atomicmock.NewSharedMemory(ctrl)
754756
mockSharedMemory.EXPECT().Apply(gomock.Any(), gomock.Any()).Return(nil)
@@ -772,6 +774,7 @@ func TestBlockAccept(t *testing.T) {
772774
},
773775
},
774776
},
777+
sharedMemory: mockSharedMemory,
775778
}
776779
},
777780
expectedErr: nil,

vms/avm/block/executor/executormock/manager.go

Lines changed: 17 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vms/avm/block/executor/manager.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ type Manager interface {
3131

3232
// Returns the ID of the most recently accepted block.
3333
LastAccepted() ids.ID
34+
SetLastAccepted(id ids.ID)
3435

3536
SetPreference(blkID ids.ID)
3637
Preferred() ids.ID
3738

3839
GetBlock(blkID ids.ID) (snowman.Block, error)
3940
GetStatelessBlock(blkID ids.ID) (block.Block, error)
40-
NewBlock(block.Block) snowman.Block
41+
NewBlock(blk block.Block, sm atomic.SharedMemory) snowman.Block
4142

4243
// VerifyTx verifies that the transaction can be issued based on the currently
4344
// preferred state. This should *not* be used to verify transactions in a block.
@@ -109,6 +110,10 @@ func (m *manager) LastAccepted() ids.ID {
109110
return m.lastAccepted
110111
}
111112

113+
func (m *manager) SetLastAccepted(blkID ids.ID) {
114+
m.lastAccepted = blkID
115+
}
116+
112117
func (m *manager) SetPreference(blockID ids.ID) {
113118
m.preferred = blockID
114119
}
@@ -122,7 +127,7 @@ func (m *manager) GetBlock(blkID ids.ID) (snowman.Block, error) {
122127
if err != nil {
123128
return nil, err
124129
}
125-
return m.NewBlock(blk), nil
130+
return m.NewBlock(blk, m.backend.Ctx.SharedMemory), nil
126131
}
127132

128133
func (m *manager) GetStatelessBlock(blkID ids.ID) (block.Block, error) {
@@ -134,10 +139,14 @@ func (m *manager) GetStatelessBlock(blkID ids.ID) (block.Block, error) {
134139
return m.state.GetBlock(blkID)
135140
}
136141

137-
func (m *manager) NewBlock(blk block.Block) snowman.Block {
142+
func (m *manager) NewBlock(
143+
blk block.Block,
144+
sm atomic.SharedMemory,
145+
) snowman.Block {
138146
return &Block{
139-
Block: blk,
140-
manager: m,
147+
Block: blk,
148+
manager: m,
149+
sharedMemory: sm,
141150
}
142151
}
143152

vms/avm/environment_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/ava-labs/avalanchego/vms/avm/block/executor"
2626
"github.com/ava-labs/avalanchego/vms/avm/config"
2727
"github.com/ava-labs/avalanchego/vms/avm/fxs"
28+
"github.com/ava-labs/avalanchego/vms/avm/state"
2829
"github.com/ava-labs/avalanchego/vms/avm/txs"
2930
"github.com/ava-labs/avalanchego/vms/avm/txs/txstest"
3031
"github.com/ava-labs/avalanchego/vms/components/avax"
@@ -113,7 +114,8 @@ func setup(tb testing.TB, c *envConfig) *environment {
113114
}
114115

115116
vm := &VM{
116-
Config: vmStaticConfig,
117+
Config: vmStaticConfig,
118+
StateMigration: state.NoMigration{},
117119
}
118120

119121
vmDynamicConfig := DefaultConfig
@@ -408,20 +410,20 @@ func issueAndAccept(
408410
require *require.Assertions,
409411
vm *VM,
410412
tx *txs.Tx,
411-
) {
413+
) ids.ID {
412414
txID, err := vm.issueTxFromRPC(tx)
413415
require.NoError(err)
414416
require.Equal(tx.ID(), txID)
415417

416-
buildAndAccept(require, vm, txID)
418+
return buildAndAccept(require, vm, txID)
417419
}
418420

419421
// buildAndAccept expects the context lock not to be held
420422
func buildAndAccept(
421423
require *require.Assertions,
422424
vm *VM,
423425
txID ids.ID,
424-
) {
426+
) ids.ID {
425427
msg, err := vm.WaitForEvent(context.Background())
426428
require.NoError(err)
427429
require.Equal(common.PendingTxs, msg)
@@ -442,4 +444,6 @@ func buildAndAccept(
442444
require.NoError(blk.Verify(context.Background()))
443445
require.NoError(vm.SetPreference(context.Background(), blk.ID()))
444446
require.NoError(blk.Accept(context.Background()))
447+
448+
return blk.ID()
445449
}

vms/avm/factory.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/ava-labs/avalanchego/utils/logging"
88
"github.com/ava-labs/avalanchego/vms"
99
"github.com/ava-labs/avalanchego/vms/avm/config"
10+
"github.com/ava-labs/avalanchego/vms/avm/state"
1011
)
1112

1213
var _ vms.Factory = (*Factory)(nil)
@@ -16,5 +17,9 @@ type Factory struct {
1617
}
1718

1819
func (f *Factory) New(logging.Logger) (interface{}, error) {
19-
return &VM{Config: f.Config}, nil
20+
return &VM{
21+
Config: f.Config,
22+
StateMigration: &state.FirewoodMigration{CommitFrequency: 1_000},
23+
},
24+
nil
2025
}

vms/avm/state/diff.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ type diff struct {
3838
addedBlockIDs map[uint64]ids.ID // map of height -> blockID
3939
addedBlocks map[ids.ID]block.Block // map of blockID -> block
4040

41-
lastAccepted ids.ID
42-
timestamp time.Time
41+
lastAccepted ids.ID
42+
lastAcceptedHeight uint64
43+
timestamp time.Time
4344
}
4445

4546
func NewDiff(
@@ -149,8 +150,9 @@ func (d *diff) GetLastAccepted() ids.ID {
149150
return d.lastAccepted
150151
}
151152

152-
func (d *diff) SetLastAccepted(lastAccepted ids.ID) {
153+
func (d *diff) SetLastAccepted(lastAccepted ids.ID, height uint64) {
153154
d.lastAccepted = lastAccepted
155+
d.lastAcceptedHeight = height
154156
}
155157

156158
func (d *diff) GetTimestamp() time.Time {
@@ -178,6 +180,6 @@ func (d *diff) Apply(state Chain) {
178180
state.AddBlock(blk)
179181
}
180182

181-
state.SetLastAccepted(d.lastAccepted)
183+
state.SetLastAccepted(d.lastAccepted, d.lastAcceptedHeight)
182184
state.SetTimestamp(d.timestamp)
183185
}

0 commit comments

Comments
 (0)