Skip to content

Commit ea6e1ec

Browse files
committed
Merkle-ize X-Chain
Signed-off-by: Joshua Kim <[email protected]>
1 parent a4d93f3 commit ea6e1ec

File tree

20 files changed

+1251
-204
lines changed

20 files changed

+1251
-204
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/executor/block.go

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

212-
func (b *Block) Accept(context.Context) error {
212+
func (b *Block) Accept(ctx context.Context) error {
213213
blkID := b.ID()
214214
defer b.manager.free(blkID)
215215

@@ -254,12 +254,17 @@ func (b *Block) Accept(context.Context) error {
254254
return err
255255
}
256256

257+
checksum, err := b.manager.state.Checksum(ctx)
258+
if err != nil {
259+
return fmt.Errorf("failed to get checksum: %w", err)
260+
}
261+
257262
b.manager.backend.Ctx.Log.Trace(
258263
"accepted block",
259264
zap.Stringer("blkID", blkID),
260265
zap.Uint64("height", b.Height()),
261266
zap.Stringer("parentID", b.Parent()),
262-
zap.Stringer("checksum", b.manager.state.Checksum()),
267+
zap.Stringer("checksum", checksum),
263268
)
264269
return nil
265270
}

vms/avm/block/executor/block_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func TestBlockVerify(t *testing.T) {
161161
parentID := ids.GenerateTestID()
162162
mockBlock.EXPECT().Parent().Return(parentID).AnyTimes()
163163

164-
mockState := statemock.NewState(ctrl)
164+
mockState := statemock.NewMockInterface(ctrl)
165165
mockState.EXPECT().GetBlock(parentID).Return(nil, errTest)
166166
return &Block{
167167
Block: mockBlock,
@@ -195,7 +195,7 @@ func TestBlockVerify(t *testing.T) {
195195
parentID := ids.GenerateTestID()
196196
mockBlock.EXPECT().Parent().Return(parentID).AnyTimes()
197197

198-
mockState := statemock.NewState(ctrl)
198+
mockState := statemock.NewMockInterface(ctrl)
199199
mockParentBlock := block.NewMockBlock(ctrl)
200200
mockParentBlock.EXPECT().Height().Return(blockHeight) // Should be blockHeight - 1
201201
mockState.EXPECT().GetBlock(parentID).Return(mockParentBlock, nil)
@@ -626,7 +626,7 @@ func TestBlockAccept(t *testing.T) {
626626
mempool, err := mempool.New("", prometheus.NewRegistry(), nil)
627627
require.NoError(t, err)
628628

629-
mockManagerState := statemock.NewState(ctrl)
629+
mockManagerState := statemock.NewMockInterface(ctrl)
630630
mockManagerState.EXPECT().CommitBatch().Return(nil, errTest)
631631
mockManagerState.EXPECT().Abort()
632632

@@ -660,7 +660,7 @@ func TestBlockAccept(t *testing.T) {
660660
mempool, err := mempool.New("", prometheus.NewRegistry(), nil)
661661
require.NoError(t, err)
662662

663-
mockManagerState := statemock.NewState(ctrl)
663+
mockManagerState := statemock.NewMockInterface(ctrl)
664664
// Note the returned batch is nil but not used
665665
// because we mock the call to shared memory
666666
mockManagerState.EXPECT().CommitBatch().Return(nil, nil)
@@ -699,7 +699,7 @@ func TestBlockAccept(t *testing.T) {
699699
mempool, err := mempool.New("", prometheus.NewRegistry(), nil)
700700
require.NoError(t, err)
701701

702-
mockManagerState := statemock.NewState(ctrl)
702+
mockManagerState := statemock.NewMockInterface(ctrl)
703703
// Note the returned batch is nil but not used
704704
// because we mock the call to shared memory
705705
mockManagerState.EXPECT().CommitBatch().Return(nil, nil)
@@ -744,12 +744,12 @@ func TestBlockAccept(t *testing.T) {
744744
mempool, err := mempool.New("", prometheus.NewRegistry(), nil)
745745
require.NoError(t, err)
746746

747-
mockManagerState := statemock.NewState(ctrl)
747+
mockManagerState := statemock.NewMockInterface(ctrl)
748748
// Note the returned batch is nil but not used
749749
// because we mock the call to shared memory
750750
mockManagerState.EXPECT().CommitBatch().Return(nil, nil)
751751
mockManagerState.EXPECT().Abort()
752-
mockManagerState.EXPECT().Checksum().Return(ids.Empty)
752+
mockManagerState.EXPECT().Checksum(gomock.Any()).Return(ids.Empty, nil)
753753

754754
mockSharedMemory := atomicmock.NewSharedMemory(ctrl)
755755
mockSharedMemory.EXPECT().Apply(gomock.Any(), gomock.Any()).Return(nil)
@@ -851,7 +851,7 @@ func TestBlockReject(t *testing.T) {
851851
require.NoError(t, err)
852852

853853
lastAcceptedID := ids.GenerateTestID()
854-
mockState := statemock.NewState(ctrl)
854+
mockState := statemock.NewMockInterface(ctrl)
855855
mockState.EXPECT().GetLastAccepted().Return(lastAcceptedID).AnyTimes()
856856
mockState.EXPECT().GetTimestamp().Return(time.Now()).AnyTimes()
857857

@@ -904,7 +904,7 @@ func TestBlockReject(t *testing.T) {
904904
require.NoError(t, err)
905905

906906
lastAcceptedID := ids.GenerateTestID()
907-
mockState := statemock.NewState(ctrl)
907+
mockState := statemock.NewMockInterface(ctrl)
908908
mockState.EXPECT().GetLastAccepted().Return(lastAcceptedID).AnyTimes()
909909
mockState.EXPECT().GetTimestamp().Return(time.Now()).AnyTimes()
910910

vms/avm/block/executor/manager.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type Manager interface {
5151
func NewManager(
5252
mempool mempool.Mempool,
5353
metrics metrics.Metrics,
54-
state state.State,
54+
state state.Interface,
5555
backend *executor.Backend,
5656
clk *mockable.Clock,
5757
onAccept func(*txs.Tx) error,
@@ -72,7 +72,7 @@ func NewManager(
7272

7373
type manager struct {
7474
backend *executor.Backend
75-
state state.State
75+
state state.Interface
7676
metrics metrics.Metrics
7777
mempool mempool.Mempool
7878
clk *mockable.Clock

vms/avm/block/executor/manager_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestManagerGetStatelessBlock(t *testing.T) {
3030
require := require.New(t)
3131
ctrl := gomock.NewController(t)
3232

33-
state := statemock.NewState(ctrl)
33+
state := statemock.NewMockInterface(ctrl)
3434
m := &manager{
3535
state: state,
3636
blkIDToState: map[ids.ID]*blockState{},
@@ -72,7 +72,7 @@ func TestManagerGetState(t *testing.T) {
7272
require := require.New(t)
7373
ctrl := gomock.NewController(t)
7474

75-
s := statemock.NewState(ctrl)
75+
s := statemock.NewMockInterface(ctrl)
7676
m := &manager{
7777
state: s,
7878
blkIDToState: map[ids.ID]*blockState{},
@@ -160,7 +160,7 @@ func TestManagerVerifyTx(t *testing.T) {
160160
lastAcceptedID := ids.GenerateTestID()
161161

162162
// These values don't matter for this test
163-
state := statemock.NewState(ctrl)
163+
state := statemock.NewMockInterface(ctrl)
164164
state.EXPECT().GetLastAccepted().Return(lastAcceptedID)
165165
state.EXPECT().GetTimestamp().Return(time.Time{})
166166

@@ -190,7 +190,7 @@ func TestManagerVerifyTx(t *testing.T) {
190190
lastAcceptedID := ids.GenerateTestID()
191191

192192
// These values don't matter for this test
193-
state := statemock.NewState(ctrl)
193+
state := statemock.NewMockInterface(ctrl)
194194
state.EXPECT().GetLastAccepted().Return(lastAcceptedID)
195195
state.EXPECT().GetTimestamp().Return(time.Time{})
196196

@@ -220,7 +220,7 @@ func TestManagerVerifyTx(t *testing.T) {
220220
lastAcceptedID := ids.GenerateTestID()
221221

222222
// These values don't matter for this test
223-
state := statemock.NewState(ctrl)
223+
state := statemock.NewMockInterface(ctrl)
224224
state.EXPECT().GetLastAccepted().Return(lastAcceptedID)
225225
state.EXPECT().GetTimestamp().Return(time.Time{})
226226

vms/avm/environment_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ func setup(tb testing.TB, c *envConfig) *environment {
113113
}
114114

115115
vm := &VM{
116-
Config: vmStaticConfig,
116+
Config: vmStaticConfig,
117+
StateMigrationFactory: NoStateMigrationFactory{},
117118
}
118119

119120
vmDynamicConfig := DefaultConfig

vms/avm/factory.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,11 @@ type Factory struct {
1616
}
1717

1818
func (f *Factory) New(logging.Logger) (interface{}, error) {
19-
return &VM{Config: f.Config}, nil
19+
return &VM{
20+
Config: f.Config,
21+
StateMigrationFactory: GForkStateMigrationFactory{
22+
CommitFrequency: 1_000,
23+
},
24+
},
25+
nil
2026
}

vms/avm/service_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,7 +2536,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
25362536
{
25372537
name: "block height not found",
25382538
serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
2539-
state := statemock.NewState(ctrl)
2539+
state := statemock.NewMockInterface(ctrl)
25402540
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(ids.Empty, database.ErrNotFound)
25412541

25422542
manager := executormock.NewManager(ctrl)
@@ -2556,7 +2556,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
25562556
{
25572557
name: "block not found",
25582558
serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
2559-
state := statemock.NewState(ctrl)
2559+
state := statemock.NewMockInterface(ctrl)
25602560
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)
25612561

25622562
manager := executormock.NewManager(ctrl)
@@ -2581,7 +2581,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
25812581
block.EXPECT().InitCtx(gomock.Any())
25822582
block.EXPECT().Txs().Return(nil)
25832583

2584-
state := statemock.NewState(ctrl)
2584+
state := statemock.NewMockInterface(ctrl)
25852585
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)
25862586

25872587
manager := executormock.NewManager(ctrl)
@@ -2606,7 +2606,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
26062606
blockBytes := []byte("hi mom")
26072607
block.EXPECT().Bytes().Return(blockBytes)
26082608

2609-
state := statemock.NewState(ctrl)
2609+
state := statemock.NewMockInterface(ctrl)
26102610
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)
26112611

26122612
expected, err := formatting.Encode(formatting.Hex, blockBytes)
@@ -2634,7 +2634,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
26342634
blockBytes := []byte("hi mom")
26352635
block.EXPECT().Bytes().Return(blockBytes)
26362636

2637-
state := statemock.NewState(ctrl)
2637+
state := statemock.NewMockInterface(ctrl)
26382638
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)
26392639

26402640
expected, err := formatting.Encode(formatting.HexC, blockBytes)
@@ -2662,7 +2662,7 @@ func TestServiceGetBlockByHeight(t *testing.T) {
26622662
blockBytes := []byte("hi mom")
26632663
block.EXPECT().Bytes().Return(blockBytes)
26642664

2665-
state := statemock.NewState(ctrl)
2665+
state := statemock.NewMockInterface(ctrl)
26662666
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)
26672667

26682668
expected, err := formatting.Encode(formatting.HexNC, blockBytes)
@@ -2740,7 +2740,7 @@ func TestServiceGetHeight(t *testing.T) {
27402740
{
27412741
name: "block not found",
27422742
serviceFunc: func(ctrl *gomock.Controller) *Service {
2743-
state := statemock.NewState(ctrl)
2743+
state := statemock.NewMockInterface(ctrl)
27442744
state.EXPECT().GetLastAccepted().Return(blockID)
27452745

27462746
manager := executormock.NewManager(ctrl)
@@ -2760,7 +2760,7 @@ func TestServiceGetHeight(t *testing.T) {
27602760
{
27612761
name: "happy path",
27622762
serviceFunc: func(ctrl *gomock.Controller) *Service {
2763-
state := statemock.NewState(ctrl)
2763+
state := statemock.NewMockInterface(ctrl)
27642764
state.EXPECT().GetLastAccepted().Return(blockID)
27652765

27662766
block := block.NewMockBlock(ctrl)

vms/avm/state/mocks_generate_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ package state
55

66
//go:generate go run go.uber.org/mock/mockgen -package=${GOPACKAGE}mock -destination=${GOPACKAGE}mock/chain.go -mock_names=Chain=Chain . Chain
77
//go:generate go run go.uber.org/mock/mockgen -package=${GOPACKAGE}mock -destination=${GOPACKAGE}mock/diff.go -mock_names=Diff=Diff . Diff
8-
//go:generate go run go.uber.org/mock/mockgen -package=${GOPACKAGE}mock -destination=${GOPACKAGE}mock/state.go -mock_names=State=State . State
8+
//go:generate go run go.uber.org/mock/mockgen -package=${GOPACKAGE}mock -destination=${GOPACKAGE}mock/state.go -mock_names=State=Interface . Interface

0 commit comments

Comments
 (0)