code.vegaprotocol.io/vega@v0.79.0/core/assets/snapshot_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package assets_test 17 18 import ( 19 "bytes" 20 "context" 21 "testing" 22 "time" 23 24 "code.vegaprotocol.io/vega/core/integration/stubs" 25 snp "code.vegaprotocol.io/vega/core/snapshot" 26 "code.vegaprotocol.io/vega/core/stats" 27 "code.vegaprotocol.io/vega/core/types" 28 "code.vegaprotocol.io/vega/libs/proto" 29 vgrand "code.vegaprotocol.io/vega/libs/rand" 30 vgtest "code.vegaprotocol.io/vega/libs/test" 31 "code.vegaprotocol.io/vega/logging" 32 "code.vegaprotocol.io/vega/paths" 33 snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 34 35 "github.com/golang/mock/gomock" 36 "github.com/stretchr/testify/require" 37 ) 38 39 func getEngineAndSnapshotEngine(t *testing.T, vegaPath paths.Paths) (*testService, *snp.Engine) { 40 t.Helper() 41 as := getTestService(t) 42 as.broker.EXPECT().Send(gomock.Any()).AnyTimes() 43 now := time.Now() 44 log := logging.NewTestLogger() 45 timeService := stubs.NewTimeStub() 46 timeService.SetTime(now) 47 statsData := stats.New(log, stats.NewDefaultConfig()) 48 config := snp.DefaultConfig() 49 snapshotEngine, err := snp.NewEngine(vegaPath, config, log, timeService, statsData.Blockchain) 50 require.NoError(t, err) 51 snapshotEngine.AddProviders(as) 52 return as, snapshotEngine 53 } 54 55 func TestSnapshotRoundTripViaEngine(t *testing.T) { 56 ctx := vgtest.VegaContext("chainid", 100) 57 58 vegaPath := paths.New(t.TempDir()) 59 60 assetEngine1, snapshotEngine1 := getEngineAndSnapshotEngine(t, vegaPath) 61 closeSnapshotEngine1 := vgtest.OnlyOnce(snapshotEngine1.Close) 62 defer closeSnapshotEngine1() 63 64 require.NoError(t, snapshotEngine1.Start(context.Background())) 65 66 for i := 0; i < 3; i++ { 67 assetName := vgrand.RandomStr(5) 68 69 _, err := assetEngine1.NewAsset(ctx, assetName, &types.AssetDetails{ 70 Source: &types.AssetDetailsBuiltinAsset{}, 71 }) 72 require.Nil(t, err) 73 74 err = assetEngine1.Enable(ctx, assetName) 75 require.Nil(t, err) 76 } 77 78 snapshotHash1, err := snapshotEngine1.SnapshotNow(ctx) 79 require.NoError(t, err) 80 81 closeSnapshotEngine1() 82 83 // Reload the engine using the previous snapshot. 84 85 _, snapshotEngine2 := getEngineAndSnapshotEngine(t, vegaPath) 86 defer snapshotEngine2.Close() 87 88 // This triggers the state restoration from the local snapshot. 89 require.NoError(t, snapshotEngine2.Start(ctx)) 90 91 snapshotHash2, _, _ := snapshotEngine2.Info() 92 93 require.Equal(t, snapshotHash1, snapshotHash2) 94 } 95 96 // test round trip of active snapshot hash and serialisation. 97 func TestActiveSnapshotRoundTrip(t *testing.T) { 98 ctx := vgtest.VegaContext("chainid", 100) 99 100 activeKey := (&types.PayloadActiveAssets{}).Key() 101 for i := 0; i < 10; i++ { 102 as := getTestService(t) 103 as.broker.EXPECT().Send(gomock.Any()).AnyTimes() 104 105 _, err := as.NewAsset(ctx, "asset1", &types.AssetDetails{ 106 Source: &types.AssetDetailsBuiltinAsset{}, 107 }) 108 require.Nil(t, err) 109 err = as.Enable(ctx, "asset1") 110 require.Nil(t, err) 111 _, err = as.NewAsset(ctx, "asset2", &types.AssetDetails{ 112 Source: &types.AssetDetailsBuiltinAsset{}, 113 }) 114 require.Nil(t, err) 115 err = as.Enable(ctx, "asset2") 116 require.Nil(t, err) 117 118 // get the serialised state 119 state, _, err := as.GetState(activeKey) 120 require.Nil(t, err) 121 122 // verify state is consistent in the absence of change 123 stateNoChange, _, err := as.GetState(activeKey) 124 require.Nil(t, err) 125 126 require.True(t, bytes.Equal(state, stateNoChange)) 127 128 // reload the state 129 var active snapshot.Payload 130 require.NoError(t, proto.Unmarshal(state, &active)) 131 payload := types.PayloadFromProto(&active) 132 133 _, err = as.LoadState(context.Background(), payload) 134 require.Nil(t, err) 135 statePostReload, _, _ := as.GetState(activeKey) 136 require.True(t, bytes.Equal(state, statePostReload)) 137 } 138 } 139 140 // test round trip of active snapshot serialisation. 141 func TestPendingSnapshotRoundTrip(t *testing.T) { 142 ctx := vgtest.VegaContext("chainid", 100) 143 pendingKey := (&types.PayloadPendingAssets{}).Key() 144 145 for i := 0; i < 10; i++ { 146 as := getTestService(t) 147 as.broker.EXPECT().Send(gomock.Any()).AnyTimes() 148 149 _, err := as.NewAsset(ctx, "asset1", &types.AssetDetails{ 150 Source: &types.AssetDetailsBuiltinAsset{}, 151 }) 152 require.Nil(t, err) 153 assetID2, err := as.NewAsset(ctx, "asset2", &types.AssetDetails{ 154 Source: &types.AssetDetailsBuiltinAsset{}, 155 }) 156 require.Nil(t, err) 157 158 // set asset 2 as pending_listing 159 require.NoError(t, as.SetPendingListing(ctx, assetID2)) 160 161 // get the serialised state 162 state, _, err := as.GetState(pendingKey) 163 require.Nil(t, err) 164 165 // verify state is consistent in the absence of change 166 stateNoChange, _, err := as.GetState(pendingKey) 167 require.Nil(t, err) 168 require.True(t, bytes.Equal(state, stateNoChange)) 169 170 // reload the state 171 var pending snapshot.Payload 172 require.NoError(t, proto.Unmarshal(state, &pending)) 173 payload := types.PayloadFromProto(&pending) 174 175 _, err = as.LoadState(context.Background(), payload) 176 require.Nil(t, err) 177 statePostReload, _, _ := as.GetState(pendingKey) 178 require.True(t, bytes.Equal(state, statePostReload)) 179 } 180 }