Skip to content

Commit d197b37

Browse files
authored
Merge branch 'main' into blobreactor
2 parents e0deabc + 18c1baf commit d197b37

File tree

7 files changed

+150
-36
lines changed

7 files changed

+150
-36
lines changed

beacon/blockchain/process_proposal.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,9 @@ func (s *Service) VerifyIncomingBlock(
261261
)
262262

263263
if shouldBuildNextBlock {
264-
// state copy makes sure that preFetchBuildData does not affect state
265-
copiedState := state.Copy(ctx)
266-
nextBlockData, errFetch = s.preFetchBuildData(copiedState, blk.GetConsensusTime())
264+
// makes sure that preFetchBuildData does not affect state
265+
ephemeralState := state.Protect(ctx)
266+
nextBlockData, errFetch = s.preFetchBuildData(ephemeralState, blk.GetConsensusTime())
267267
if errFetch != nil {
268268
// We don't return with err if pre-fetch fails. Instead we log the issue
269269
// and still move to process the current block. Next block can always be
@@ -302,9 +302,9 @@ func (s *Service) VerifyIncomingBlock(
302302
)
303303

304304
if shouldBuildNextBlock {
305-
// state copy makes sure that preFetchBuildDataForSuccess does not affect state
306-
copiedState := state.Copy(ctx)
307-
nextBlockData, errFetch = s.preFetchBuildData(copiedState, blk.GetConsensusTime())
305+
// makes sure that preFetchBuildDataForSuccess does not affect state
306+
ephemeralState := state.Protect(ctx)
307+
nextBlockData, errFetch = s.preFetchBuildData(ephemeralState, blk.GetConsensusTime())
308308
if errFetch != nil {
309309
// We don't mark the block as rejected if it is valid but pre-fetch fails.
310310
// Instead we log the issue and move to process the current block.

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/crate-crypto/go-kzg-4844 v1.1.0
2929
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
3030
github.com/go-faster/xor v1.0.0
31-
github.com/go-playground/validator/v10 v10.27.0
31+
github.com/go-playground/validator/v10 v10.28.0
3232
github.com/golang-jwt/jwt/v5 v5.3.0
3333
github.com/hashicorp/go-metrics v0.5.4
3434
github.com/hashicorp/golang-lru/v2 v2.0.7
@@ -50,7 +50,7 @@ require (
5050
github.com/spf13/viper v1.21.0
5151
github.com/umbracle/fastrlp v0.1.0
5252
go.uber.org/automaxprocs v1.6.0
53-
golang.org/x/crypto v0.42.0
53+
golang.org/x/crypto v0.43.0
5454
golang.org/x/sync v0.17.0
5555
sigs.k8s.io/yaml v1.6.0
5656
)
@@ -129,7 +129,7 @@ require (
129129
github.com/fatih/color v1.18.0 // indirect
130130
github.com/felixge/httpsnoop v1.0.4 // indirect
131131
github.com/fsnotify/fsnotify v1.9.0 // indirect
132-
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
132+
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
133133
github.com/getsentry/sentry-go v0.33.0 // indirect
134134
github.com/ghodss/yaml v1.0.0 // indirect
135135
github.com/go-kit/log v0.2.1 // indirect
@@ -253,10 +253,10 @@ require (
253253
go.yaml.in/yaml/v3 v3.0.4 // indirect
254254
golang.org/x/arch v0.17.0 // indirect
255255
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
256-
golang.org/x/net v0.43.0 // indirect
257-
golang.org/x/sys v0.36.0 // indirect
258-
golang.org/x/term v0.35.0 // indirect
259-
golang.org/x/text v0.29.0 // indirect
256+
golang.org/x/net v0.45.0 // indirect
257+
golang.org/x/sys v0.37.0 // indirect
258+
golang.org/x/term v0.36.0 // indirect
259+
golang.org/x/text v0.30.0 // indirect
260260
golang.org/x/time v0.11.0 // indirect
261261
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
262262
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect

go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
240240
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
241241
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
242242
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
243-
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
244-
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
243+
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
244+
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
245245
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
246246
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
247247
github.com/getsentry/sentry-go v0.33.0 h1:YWyDii0KGVov3xOaamOnF0mjOrqSjBqwv48UEzn7QFg=
@@ -280,8 +280,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
280280
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
281281
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
282282
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
283-
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
284-
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
283+
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
284+
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
285285
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
286286
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
287287
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
@@ -798,8 +798,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
798798
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
799799
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
800800
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
801-
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
802-
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
801+
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
802+
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
803803
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
804804
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
805805
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
@@ -830,8 +830,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
830830
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
831831
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
832832
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
833-
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
834-
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
833+
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
834+
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
835835
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
836836
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
837837
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -893,20 +893,20 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
893893
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
894894
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
895895
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
896-
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
897-
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
896+
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
897+
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
898898
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
899899
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
900-
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
901-
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
900+
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
901+
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
902902
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
903903
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
904904
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
905905
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
906906
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
907907
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
908-
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
909-
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
908+
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
909+
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
910910
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
911911
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
912912
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

node-api/backend/getters.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ func (b *Backend) StateAndSlotFromHeight(height int64) (ReadOnlyBeaconState, mat
6363
// Copy the state to ensure clients potential changes won't pollute the state
6464
// Also we make sure to create the copy in a thread-safe way via the muCms mutex.
6565
ms := b.cms.CacheMultiStore()
66-
copyCtx := sdk.NewContext(ms, true, log.NewNopLogger())
67-
copyGenesisState := b.genesisState.Copy(copyCtx)
68-
return copyGenesisState, 0, nil
66+
ctx := sdk.NewContext(ms, true, log.NewNopLogger())
67+
ephemeralGenesisState := b.genesisState.Protect(ctx)
68+
return ephemeralGenesisState, 0, nil
6969
}
7070

7171
height = max(0, height) // CreateQueryContext uses 0 to pick latest height.

state-transition/core/state/statedb.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ func NewBeaconStateFromDB(
5757
}
5858
}
5959

60-
// Copy returns a copy of the beacon state.
61-
func (s *StateDB) Copy(ctx context.Context) *StateDB {
60+
// Protect returns an almost copy of stateDB. Specifically Protect guarantees that:
61+
// - No changes done on the returned state will affect the original state
62+
// - However, changes done on the original state will be carried over to the returned state.
63+
// The behaviour is probably best understood by considering the context hosts a stack of cache layers.
64+
// So write operations to the top cache won't be flushed to the lower layer but read operations will walk
65+
// through the cache stack, so bubbling up changes from the lower layers to the top ones.
66+
func (s *StateDB) Protect(ctx context.Context) *StateDB {
6267
return NewBeaconStateFromDB(s.KVStore.Copy(ctx), s.cs, s.logger, s.telemetrySink)
6368
}
6469

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
//
3+
// Copyright (C) 2025, Berachain Foundation. All rights reserved.
4+
// Use of this software is governed by the Business Source License included
5+
// in the LICENSE file of this repository and at www.mariadb.com/bsl11.
6+
//
7+
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY
8+
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER
9+
// VERSIONS OF THE LICENSED WORK.
10+
//
11+
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF
12+
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF
13+
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE).
14+
//
15+
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
16+
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
17+
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
18+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
19+
// TITLE.
20+
21+
package state_test
22+
23+
import (
24+
"testing"
25+
26+
"cosmossdk.io/collections"
27+
"cosmossdk.io/log"
28+
"cosmossdk.io/store"
29+
sdkmetrics "cosmossdk.io/store/metrics"
30+
storetypes "cosmossdk.io/store/types"
31+
"github.com/berachain/beacon-kit/config/spec"
32+
ctypes "github.com/berachain/beacon-kit/consensus-types/types"
33+
"github.com/berachain/beacon-kit/node-core/components/metrics"
34+
"github.com/berachain/beacon-kit/primitives/common"
35+
"github.com/berachain/beacon-kit/primitives/math"
36+
"github.com/berachain/beacon-kit/state-transition/core/state"
37+
"github.com/berachain/beacon-kit/storage"
38+
"github.com/berachain/beacon-kit/storage/beacondb"
39+
"github.com/berachain/beacon-kit/storage/db"
40+
dbm "github.com/cosmos/cosmos-db"
41+
sdk "github.com/cosmos/cosmos-sdk/types"
42+
"github.com/stretchr/testify/require"
43+
)
44+
45+
func TestStateProtect(t *testing.T) {
46+
t.Parallel()
47+
48+
db, err := db.OpenDB("", dbm.MemDBBackend)
49+
require.NoError(t, err)
50+
51+
cs, errSpec := spec.MainnetChainSpec()
52+
require.NoError(t, errSpec)
53+
54+
var (
55+
nopLog = log.NewNopLogger()
56+
nopMetrics = sdkmetrics.NewNoOpMetrics()
57+
)
58+
59+
cms := store.NewCommitMultiStore(db, nopLog, nopMetrics)
60+
cms.MountStoreWithDB(testStoreKey, storetypes.StoreTypeIAVL, nil)
61+
require.NoError(t, cms.LoadLatestVersion())
62+
63+
backendStoreService := &storage.KVStoreService{Key: testStoreKey}
64+
kvStore := beacondb.New(backendStoreService)
65+
66+
ms := cms.CacheMultiStore()
67+
sdkCtx := sdk.NewContext(ms, true, nopLog)
68+
originalState := state.NewBeaconStateFromDB(
69+
kvStore.WithContext(sdkCtx),
70+
cs,
71+
sdkCtx.Logger(),
72+
metrics.NewNoOpTelemetrySink(),
73+
)
74+
75+
protectingState := originalState.Protect(sdkCtx)
76+
77+
// 1- set an attribute in the original state and show
78+
// that value is carried over the protecting state
79+
wantSlot := math.Slot(1234)
80+
require.NoError(t, originalState.SetSlot(wantSlot))
81+
82+
gotSlot, err := protectingState.GetSlot()
83+
require.NoError(t, err)
84+
require.Equal(t, wantSlot, gotSlot)
85+
86+
// 2- Show that modifying the protecting state
87+
// does not affect the original state
88+
wantFork := &ctypes.Fork{
89+
PreviousVersion: common.Version{0x11, 0x22, 0x33, 0x44},
90+
CurrentVersion: common.Version{0xff, 0xff, 0xff, 0xff},
91+
Epoch: math.Epoch(1234),
92+
}
93+
require.NoError(t, protectingState.SetFork(wantFork))
94+
95+
_, err = originalState.GetFork()
96+
require.ErrorIs(t, err, collections.ErrNotFound)
97+
98+
// 3- Show that changes made to original state after protection
99+
// are carried over the protecting state
100+
wantEthIdx := uint64(1987)
101+
require.NoError(t, originalState.SetEth1DepositIndex(wantEthIdx))
102+
103+
gotEthIdx, err := protectingState.GetEth1DepositIndex()
104+
require.NoError(t, err)
105+
require.Equal(t, wantEthIdx, gotEthIdx)
106+
}
107+
108+
var testStoreKey = storetypes.NewKVStoreKey("test-stateDB")

testing/simulated/utils.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,9 @@ func ComputeAndSetStateRoot(
326326
block *ctypes.BeaconBlock,
327327
) (*ctypes.BeaconBlock, error) {
328328

329-
// Copy the current state from the storage backend.
330-
stateDBCopy := storageBackend.StateFromContext(queryCtx).Copy(queryCtx)
329+
// Create an ephemeral state out of storage backend to avoid polluting
330+
// the original state
331+
ephemeralState := storageBackend.StateFromContext(queryCtx).Protect(queryCtx)
331332

332333
// Create a transition context with the provided consensus time and proposer address.
333334
txCtx := transition.NewTransitionCtx(
@@ -340,13 +341,13 @@ func ComputeAndSetStateRoot(
340341
WithMeterGas(false)
341342

342343
// Run the state transition.
343-
_, err := stateProcessor.Transition(txCtx, stateDBCopy, block)
344+
_, err := stateProcessor.Transition(txCtx, ephemeralState, block)
344345
if err != nil {
345346
return nil, fmt.Errorf("state transition failed: %w", err)
346347
}
347348

348349
// Compute the new state root from the updated state.
349-
newStateRoot := stateDBCopy.HashTreeRoot()
350+
newStateRoot := ephemeralState.HashTreeRoot()
350351
block.SetStateRoot(newStateRoot)
351352
return block, nil
352353
}

0 commit comments

Comments
 (0)