Skip to content

Commit 49b58c5

Browse files
authored
refactor: remove old layout code (part 1) (#3539)
* refactor(deprecatedmigration): introduce oldlayout accessors for legacy transaction handling - Added a new package `oldlayout` containing accessors for the old transaction layout. - Updated migration code to utilize the new accessors for retrieving blocks and transactions by block number. - Refactored existing migration functions to replace direct calls to the core transaction layout with calls to the new `oldlayout` package. * tests(deprecatedmigration):new test state + update tests to use it * refactor(blocktransactions): new txlayout package, update blocktransactions tests to use it * test: use the new txlayout pkg in the deprecatedmigration pkg, and remove the oldlayout pkg * chore(txlayout): remove unused methods and add pkg description * test(deprecatedmigration): clean up state_test.go by removing commented-out code * test(txlayout): copy tests from the core pkg + add missing methods from the original code * refactor(blockchain): remove transaction layout option
1 parent 0eb0d7a commit 49b58c5

9 files changed

Lines changed: 785 additions & 43 deletions

File tree

blockchain/blockchain.go

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,13 @@ type Blockchain struct {
8989

9090
// options holds configuration for constructing a Blockchain.
9191
type options struct {
92-
listener EventListener
93-
transactionLayout core.TransactionLayout
94-
stateVersion bool
92+
listener EventListener
93+
stateVersion bool
9594
}
9695

9796
// Option is a functional option for configuring Blockchain options.
9897
type Option func(*options)
9998

100-
// Deprecated: Production code only supports CombinedLayout. Kept for testing purposes,
101-
// remove when [deprecatedmigration] is no longer relevant.
102-
//
103-
// WithTransactionLayout sets the transaction storage layout.
104-
func WithTransactionLayout(layout core.TransactionLayout) Option {
105-
return func(o *options) {
106-
o.transactionLayout = layout
107-
}
108-
}
109-
11099
// WithListener sets the event listener for the blockchain.
111100
func WithListener(listener EventListener) Option {
112101
return func(o *options) {
@@ -121,9 +110,8 @@ func WithNewState(enabled bool) Option {
121110

122111
func New(database db.KeyValueStore, network *utils.Network, opts ...Option) *Blockchain {
123112
o := options{
124-
listener: &SelectiveListener{},
125-
transactionLayout: core.TransactionLayoutCombined,
126-
stateVersion: false,
113+
listener: &SelectiveListener{},
114+
stateVersion: false,
127115
}
128116
for _, opt := range opts {
129117
opt(&o)
@@ -144,22 +132,17 @@ func New(database db.KeyValueStore, network *utils.Network, opts ...Option) *Blo
144132
l1HeadFeed: feed.New[*core.L1Head](),
145133
cachedFilters: &cachedFilters,
146134
runningFilter: runningFilter,
147-
transactionLayout: o.transactionLayout,
135+
transactionLayout: core.TransactionLayoutCombined,
148136
stateBackend: statebackend.New(
149137
database,
150138
runningFilter,
151139
network,
152140
o.stateVersion,
153-
o.transactionLayout,
141+
core.TransactionLayoutCombined,
154142
),
155143
}
156144
}
157145

158-
// TransactionLayout returns the transaction storage layout used by this blockchain
159-
func (b *Blockchain) TransactionLayout() core.TransactionLayout {
160-
return b.transactionLayout
161-
}
162-
163146
func (b *Blockchain) Network() *utils.Network {
164147
return b.network
165148
}

deprecatedmigration/l1handlermapping/ingestor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/NethermindEth/juno/core"
77
"github.com/NethermindEth/juno/db"
88
"github.com/NethermindEth/juno/deprecatedmigration/progresslogger"
9+
"github.com/NethermindEth/juno/migration/blocktransactions/txlayout"
910
"github.com/NethermindEth/juno/migration/pipeline"
1011
"github.com/NethermindEth/juno/migration/semaphore"
1112
)
@@ -39,7 +40,7 @@ var _ pipeline.State[uint64, db.Batch] = (*ingestor)(nil)
3940

4041
func (i *ingestor) Run(index int, blockNumber uint64, outputs chan<- db.Batch) error {
4142
// Force per-tx layout because this migration was created before the combined layout
42-
txns, err := core.TransactionLayoutPerTx.TransactionsByBlockNumber(i.database, blockNumber)
43+
txns, err := txlayout.TransactionLayoutPerTx.TransactionsByBlockNumber(i.database, blockNumber)
4344
if err != nil {
4445
return fmt.Errorf("failed to get transactions for block %d: %w", blockNumber, err)
4546
}

deprecatedmigration/l1handlermapping/migrator_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/NethermindEth/juno/db"
1111
"github.com/NethermindEth/juno/db/memory"
1212
"github.com/NethermindEth/juno/deprecatedmigration/l1handlermapping"
13+
"github.com/NethermindEth/juno/migration/blocktransactions/txlayout"
1314
"github.com/NethermindEth/juno/utils"
1415
"github.com/stretchr/testify/require"
1516
)
@@ -58,7 +59,7 @@ func TestRecalculateL1HandlerMsgHashesToTxnHashes(t *testing.T) {
5859
// Write transactions using per-tx layout (migration reads from per-tx layout)
5960
require.NoError(
6061
t,
61-
core.TransactionLayoutPerTx.WriteTransactionsAndReceipts(batch, blockNum, txs, receipts),
62+
txlayout.TransactionLayoutPerTx.WriteTransactionsAndReceipts(batch, blockNum, txs, receipts),
6263
)
6364

6465
// Track L1Handler transactions for verification

deprecatedmigration/migration.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/NethermindEth/juno/deprecatedmigration/casmhashmetadata"
2828
"github.com/NethermindEth/juno/deprecatedmigration/l1handlermapping"
2929
"github.com/NethermindEth/juno/encoder"
30+
"github.com/NethermindEth/juno/migration/blocktransactions/txlayout"
3031
"github.com/NethermindEth/juno/starknet"
3132
"github.com/NethermindEth/juno/utils"
3233
"github.com/bits-and-blooms/bitset"
@@ -311,7 +312,7 @@ func relocateContractStorageRootKeys(txn db.IndexedBatch, _ *utils.Network) erro
311312
// recalculateBloomFilters updates bloom filters in block headers to match what the most recent implementation expects
312313
func recalculateBloomFilters(txn db.IndexedBatch, _ *utils.Network) error {
313314
for blockNumber := uint64(0); ; blockNumber++ {
314-
block, err := core.TransactionLayoutPerTx.BlockByNumber(txn, blockNumber)
315+
block, err := txlayout.TransactionLayoutPerTx.BlockByNumber(txn, blockNumber)
315316
if err != nil {
316317
if errors.Is(err, db.ErrKeyNotFound) {
317318
return nil
@@ -539,7 +540,7 @@ func processBlocks(txn db.IndexedBatch, processBlock func(uint64, *sync.Mutex) e
539540
func calculateBlockCommitments(txn db.IndexedBatch, network *utils.Network) error {
540541
processBlockFunc := func(blockNumber uint64, txnLock *sync.Mutex) error {
541542
txnLock.Lock()
542-
block, err := core.TransactionLayoutPerTx.BlockByNumber(txn, blockNumber)
543+
block, err := txlayout.TransactionLayoutPerTx.BlockByNumber(txn, blockNumber)
543544
txnLock.Unlock()
544545
if err != nil {
545546
return err
@@ -560,7 +561,7 @@ func calculateBlockCommitments(txn db.IndexedBatch, network *utils.Network) erro
560561
func calculateL1MsgHashes2(txn db.IndexedBatch, n *utils.Network) error {
561562
processBlockFunc := func(blockNumber uint64, txnLock *sync.Mutex) error {
562563
txnLock.Lock()
563-
txns, err := core.TransactionLayoutPerTx.TransactionsByBlockNumber(txn, blockNumber)
564+
txns, err := txlayout.TransactionLayoutPerTx.TransactionsByBlockNumber(txn, blockNumber)
564565
txnLock.Unlock()
565566
if err != nil {
566567
return err

deprecatedmigration/migration_pkg_test.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,9 @@ func TestChangeTrieNodeEncoding(t *testing.T) {
190190

191191
func TestCalculateBlockCommitments(t *testing.T) {
192192
testdb := memory.New()
193-
chain := blockchain.New(
193+
state := NewTestState(
194194
testdb,
195195
&utils.Mainnet,
196-
//nolint:staticcheck // deprecated option used in test
197-
blockchain.WithTransactionLayout(core.TransactionLayoutPerTx),
198196
)
199197
client := feeder.NewTestClient(t, &utils.Mainnet)
200198
gw := adaptfeeder.New(client)
@@ -204,26 +202,24 @@ func TestCalculateBlockCommitments(t *testing.T) {
204202
require.NoError(t, err)
205203
su, err := gw.StateUpdate(t.Context(), i)
206204
require.NoError(t, err)
207-
require.NoError(t, chain.Store(b, &core.BlockCommitments{}, su, nil))
205+
require.NoError(t, state.Store(b, &core.BlockCommitments{}, su, nil))
208206
}
209207

210208
require.NoError(t, testdb.Update(func(txn db.IndexedBatch) error {
211209
return calculateBlockCommitments(txn, &utils.Mainnet)
212210
}))
213211
for i := range uint64(3) {
214-
b, err := chain.BlockCommitmentsByNumber(i)
212+
b, err := core.GetBlockCommitmentByBlockNum(testdb, i)
215213
require.NoError(t, err)
216214
assert.NotNil(t, b.TransactionCommitment)
217215
}
218216
}
219217

220218
func TestL1HandlerTxns(t *testing.T) {
221219
testdb := memory.New()
222-
chain := blockchain.New(
220+
state := NewTestState(
223221
testdb,
224222
&utils.Sepolia,
225-
//nolint:staticcheck // deprecated option used in test
226-
blockchain.WithTransactionLayout(core.TransactionLayoutPerTx),
227223
)
228224
client := feeder.NewTestClient(t, &utils.Sepolia)
229225
gw := adaptfeeder.New(client)
@@ -233,7 +229,7 @@ func TestL1HandlerTxns(t *testing.T) {
233229
require.NoError(t, err)
234230
su, err := gw.StateUpdate(t.Context(), i)
235231
require.NoError(t, err)
236-
require.NoError(t, chain.Store(b, &core.BlockCommitments{}, su, nil))
232+
require.NoError(t, state.Store(b, &core.BlockCommitments{}, su, nil))
237233
}
238234

239235
msgHash := common.HexToHash("0x42e76df4e3d5255262929c27132bd0d295a8d3db2cfe63d2fcd061c7a7a7ab34")
@@ -244,7 +240,7 @@ func TestL1HandlerTxns(t *testing.T) {
244240
}))
245241

246242
// Ensure the key has been deleted
247-
_, err := chain.L1HandlerTxnHash(&msgHash)
243+
_, err := core.GetL1HandlerTxnHashByMsgHash(testdb, msgHash.Bytes())
248244
require.ErrorIs(t, err, db.ErrKeyNotFound)
249245

250246
// Recalculate and store the L1 message hashes
@@ -253,7 +249,7 @@ func TestL1HandlerTxns(t *testing.T) {
253249
}))
254250

255251
msgHash = common.HexToHash("0x42e76df4e3d5255262929c27132bd0d295a8d3db2cfe63d2fcd061c7a7a7ab34")
256-
l1HandlerTxnHash, err := chain.L1HandlerTxnHash(&msgHash)
252+
l1HandlerTxnHash, err := core.GetL1HandlerTxnHashByMsgHash(testdb, msgHash.Bytes())
257253
require.NoError(t, err)
258254
assert.Equal(t, l1HandlerTxnHash.String(), "0x785c2ada3f53fbc66078d47715c27718f92e6e48b96372b36e5197de69b82b5")
259255
}

deprecatedmigration/state_test.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package deprecatedmigration
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/NethermindEth/juno/core"
8+
"github.com/NethermindEth/juno/core/felt"
9+
"github.com/NethermindEth/juno/db"
10+
"github.com/NethermindEth/juno/migration/blocktransactions/txlayout"
11+
"github.com/NethermindEth/juno/utils"
12+
)
13+
14+
// testStateBackend is a copy of the [statebackend.deprecatedStateBackend] type
15+
// that stores the state using the old layout.
16+
//
17+
// Juno now uses a new layout to store transactions and receipts on the database,
18+
// but there are some old migrations that use the old layout. These migrations
19+
// can not be tested using the current state code, since it uses the new layout.
20+
// [testStateBackend] was created specifically to solve this problem.
21+
type testStateBackend struct {
22+
database db.KeyValueStore
23+
network *utils.Network
24+
}
25+
26+
// NewTestState creates a new test state that stores the data using the old layout.
27+
func NewTestState(
28+
database db.KeyValueStore,
29+
network *utils.Network,
30+
) *testStateBackend {
31+
return &testStateBackend{
32+
database: database,
33+
network: network,
34+
}
35+
}
36+
37+
func (b *testStateBackend) Store(
38+
block *core.Block,
39+
blockCommitments *core.BlockCommitments,
40+
stateUpdate *core.StateUpdate,
41+
newClasses map[felt.Felt]core.ClassDefinition,
42+
) error {
43+
//nolint:staticcheck,nolintlint // used by old state
44+
err := b.database.Update(func(txn db.IndexedBatch) error {
45+
if err := verifyBlockSuccession(txn, block); err != nil {
46+
return err
47+
}
48+
err := core.NewDeprecatedState(txn).Update(block.Header, stateUpdate, newClasses, false)
49+
if err != nil {
50+
return err
51+
}
52+
53+
return writeBlockContent(
54+
txn,
55+
block,
56+
stateUpdate,
57+
blockCommitments,
58+
newClasses,
59+
)
60+
})
61+
if err != nil {
62+
return err
63+
}
64+
65+
return nil
66+
}
67+
68+
func verifyBlockSuccession(reader db.KeyValueReader, block *core.Block) error {
69+
ErrParentDoesNotMatchHead := errors.New("block's parent hash does not match head block hash")
70+
if err := core.CheckBlockVersion(block.ProtocolVersion); err != nil {
71+
return err
72+
}
73+
74+
expectedBlockNumber := uint64(0)
75+
expectedParentHash := &felt.Zero
76+
77+
h, err := headsHeader(reader)
78+
if err == nil {
79+
expectedBlockNumber = h.Number + 1
80+
expectedParentHash = h.Hash
81+
} else if !errors.Is(err, db.ErrKeyNotFound) {
82+
return err
83+
}
84+
85+
if expectedBlockNumber != block.Number {
86+
return fmt.Errorf("expected block #%d, got block #%d", expectedBlockNumber, block.Number)
87+
}
88+
if !block.ParentHash.Equal(expectedParentHash) {
89+
return ErrParentDoesNotMatchHead
90+
}
91+
92+
return nil
93+
}
94+
95+
func headsHeader(reader db.KeyValueReader) (*core.Header, error) {
96+
height, err := core.GetChainHeight(reader)
97+
if err != nil {
98+
return nil, err
99+
}
100+
return core.GetBlockHeaderByNumber(reader, height)
101+
}
102+
103+
func writeBlockContent(
104+
writer db.Batch,
105+
block *core.Block,
106+
stateUpdate *core.StateUpdate,
107+
commitments *core.BlockCommitments,
108+
newClasses map[felt.Felt]core.ClassDefinition,
109+
) error {
110+
if err := core.WriteBlockHeader(writer, block.Header); err != nil {
111+
return err
112+
}
113+
114+
if err := txlayout.TransactionLayoutPerTx.WriteTransactionsAndReceipts(
115+
writer,
116+
block.Number,
117+
block.Transactions,
118+
block.Receipts,
119+
); err != nil {
120+
return err
121+
}
122+
123+
if err := core.WriteStateUpdateByBlockNum(writer, block.Number, stateUpdate); err != nil {
124+
return err
125+
}
126+
127+
if err := core.WriteBlockCommitment(writer, block.Number, commitments); err != nil {
128+
return err
129+
}
130+
131+
if err := core.WriteL1HandlerMsgHashes(writer, block.Transactions); err != nil {
132+
return err
133+
}
134+
135+
// we use v1 directly since the tests that use this function are using
136+
// protocol < 0.14.1 blocks
137+
if err := storeCasmHashMetadataV1(
138+
writer,
139+
block.Number,
140+
stateUpdate,
141+
newClasses,
142+
); err != nil {
143+
return err
144+
}
145+
146+
return core.WriteChainHeight(writer, block.Number)
147+
}
148+
149+
func storeCasmHashMetadataV1(
150+
writer db.KeyValueWriter,
151+
blockNumber uint64,
152+
stateUpdate *core.StateUpdate,
153+
newClasses map[felt.Felt]core.ClassDefinition,
154+
) error {
155+
for sierraClassHash, casmHash := range stateUpdate.StateDiff.DeclaredV1Classes {
156+
casmHashV1 := (*felt.CasmClassHash)(casmHash)
157+
158+
classDef, ok := newClasses[sierraClassHash]
159+
if !ok {
160+
return fmt.Errorf("class %s not available in newClasses at block %d",
161+
sierraClassHash.String(),
162+
blockNumber,
163+
)
164+
}
165+
166+
sierraClass, ok := classDef.(*core.SierraClass)
167+
if !ok {
168+
return fmt.Errorf("class %s must be a SierraClass at block %d",
169+
sierraClassHash.String(),
170+
blockNumber,
171+
)
172+
}
173+
174+
v2Hash := sierraClass.Compiled.Hash(core.HashVersionV2)
175+
casmHashV2 := felt.CasmClassHash(v2Hash)
176+
177+
metadata := core.NewCasmHashMetadataDeclaredV1(blockNumber, casmHashV1, &casmHashV2)
178+
err := core.WriteClassCasmHashMetadata(
179+
writer,
180+
(*felt.SierraClassHash)(&sierraClassHash),
181+
&metadata,
182+
)
183+
if err != nil {
184+
return err
185+
}
186+
}
187+
return nil
188+
}

0 commit comments

Comments
 (0)