Skip to content

Commit 4ff174d

Browse files
committed
Move pending to sync package
In order to moved handling of pending to synchroniser the following changes needed to be made: - Add database to synchroniser, so that pending state can be served - Blockchain and Events Filter have a pendingBlockFn() which returns the pending block. Due to import cycle pending struct could not be referenced, therefore, the anonymous function is passed. - Add PendingBlock() to return just the pending block, this was mainly added to support the pendingBlockFn(). - In rpc package the pending block and state is retrieved through synchroniser. Therefore, receipt and transaction handler now check the pending block for the requested transaction/receipt.
1 parent fb75cd6 commit 4ff174d

27 files changed

+503
-469
lines changed

blockchain/blockchain.go

Lines changed: 12 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/binary"
66
"errors"
77
"fmt"
8-
"sync/atomic"
98

109
"github.com/Masterminds/semver/v3"
1110
"github.com/NethermindEth/juno/core"
@@ -39,14 +38,11 @@ type Reader interface {
3938
HeadState() (core.StateReader, StateCloser, error)
4039
StateAtBlockHash(blockHash *felt.Felt) (core.StateReader, StateCloser, error)
4140
StateAtBlockNumber(blockNumber uint64) (core.StateReader, StateCloser, error)
42-
PendingState() (core.StateReader, StateCloser, error)
4341

4442
BlockCommitmentsByNumber(blockNumber uint64) (*core.BlockCommitments, error)
4543

4644
EventFilter(from *felt.Felt, keys [][]felt.Felt) (EventFilterer, error)
4745

48-
Pending() (*Pending, error)
49-
5046
Network() *utils.Network
5147
}
5248

@@ -56,7 +52,7 @@ var (
5652
SupportedStarknetVersion = semver.MustParse("0.13.3")
5753
)
5854

59-
func checkBlockVersion(protocolVersion string) error {
55+
func CheckBlockVersion(protocolVersion string) error {
6056
blockVer, err := core.ParseBlockVersion(protocolVersion)
6157
if err != nil {
6258
return err
@@ -81,22 +77,21 @@ func copyWithoutPatch(v *semver.Version) *semver.Version {
8177

8278
var _ Reader = (*Blockchain)(nil)
8379

84-
// Todo: Remove after pending is moved to sychcroniser
85-
var pending atomic.Pointer[Pending]
86-
8780
// Blockchain is responsible for keeping track of all things related to the Starknet blockchain
8881
type Blockchain struct {
89-
network *utils.Network
90-
database db.DB
91-
listener EventListener
82+
network *utils.Network
83+
database db.DB
84+
listener EventListener
85+
pendingBlockFn func() *core.Block
9286
}
9387

94-
func New(database db.DB, network *utils.Network) *Blockchain {
88+
func New(database db.DB, network *utils.Network, pendingBlockFn func() *core.Block) *Blockchain {
9589
RegisterCoreTypesToEncoder()
9690
return &Blockchain{
97-
database: database,
98-
network: network,
99-
listener: &SelectiveListener{},
91+
database: database,
92+
network: network,
93+
listener: &SelectiveListener{},
94+
pendingBlockFn: pendingBlockFn,
10095
}
10196
}
10297

@@ -266,24 +261,6 @@ func (b *Blockchain) TransactionByHash(hash *felt.Felt) (core.Transaction, error
266261
return transaction, b.database.View(func(txn db.Transaction) error {
267262
var err error
268263
transaction, err = transactionByHash(txn, hash)
269-
270-
// not found in the canonical blocks, try pending
271-
if errors.Is(err, db.ErrKeyNotFound) {
272-
var pending *Pending
273-
pending, err = pendingBlock(txn)
274-
if err != nil {
275-
return err
276-
}
277-
278-
for _, t := range pending.Block.Transactions {
279-
if hash.Equal(t.Hash()) {
280-
transaction = t
281-
return nil
282-
}
283-
}
284-
return db.ErrKeyNotFound
285-
}
286-
287264
return err
288265
})
289266
}
@@ -299,29 +276,6 @@ func (b *Blockchain) Receipt(hash *felt.Felt) (*core.TransactionReceipt, *felt.F
299276
return receipt, blockHash, blockNumber, b.database.View(func(txn db.Transaction) error {
300277
var err error
301278
receipt, blockHash, blockNumber, err = receiptByHash(txn, hash)
302-
303-
// not found in the canonical blocks, try pending
304-
if errors.Is(err, db.ErrKeyNotFound) {
305-
var pending *Pending
306-
pending, err = pendingBlock(txn)
307-
if err != nil {
308-
if !errors.Is(err, ErrPendingBlockNotFound) {
309-
return err
310-
}
311-
return db.ErrKeyNotFound
312-
}
313-
314-
for i, t := range pending.Block.Transactions {
315-
if hash.Equal(t.Hash()) {
316-
receipt = pending.Block.Receipts[i]
317-
blockHash = nil
318-
blockNumber = 0
319-
return nil
320-
}
321-
}
322-
return db.ErrKeyNotFound
323-
}
324-
325279
return err
326280
})
327281
}
@@ -407,7 +361,7 @@ func (b *Blockchain) VerifyBlock(block *core.Block) error {
407361
}
408362

409363
func verifyBlock(txn db.Transaction, block *core.Block) error {
410-
if err := checkBlockVersion(block.ProtocolVersion); err != nil {
364+
if err := CheckBlockVersion(block.ProtocolVersion); err != nil {
411365
return err
412366
}
413367

@@ -865,7 +819,7 @@ func (b *Blockchain) EventFilter(from *felt.Felt, keys [][]felt.Felt) (EventFilt
865819
return nil, err
866820
}
867821

868-
return newEventFilter(txn, from, keys, 0, latest, &pending), nil
822+
return newEventFilter(txn, from, keys, 0, latest, b.pendingBlockFn), nil
869823
}
870824

871825
// RevertHead reverts the head block
@@ -975,87 +929,3 @@ func removeTxsAndReceipts(txn db.Transaction, blockNumber, numTxs uint64) error
975929

976930
return nil
977931
}
978-
979-
// StorePending stores a pending block given that it is for the next height
980-
func (b *Blockchain) StorePending(p *Pending) error {
981-
err := checkBlockVersion(p.Block.ProtocolVersion)
982-
if err != nil {
983-
return err
984-
}
985-
return b.database.View(func(txn db.Transaction) error {
986-
expectedParentHash := new(felt.Felt)
987-
h, err := headsHeader(txn)
988-
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
989-
return err
990-
} else if err == nil {
991-
expectedParentHash = h.Hash
992-
}
993-
994-
if !expectedParentHash.Equal(p.Block.ParentHash) {
995-
return ErrParentDoesNotMatchHead
996-
}
997-
998-
if existingPending, err := pendingBlock(txn); err == nil {
999-
if existingPending.Block.TransactionCount >= p.Block.TransactionCount {
1000-
// ignore the incoming pending if it has fewer transactions than the one we already have
1001-
return nil
1002-
}
1003-
} else if !errors.Is(err, ErrPendingBlockNotFound) {
1004-
return err
1005-
}
1006-
1007-
if h != nil {
1008-
p.Block.Number = h.Number + 1
1009-
}
1010-
pending.Store(p)
1011-
1012-
return nil
1013-
})
1014-
}
1015-
1016-
func pendingBlock(txn db.Transaction) (*Pending, error) {
1017-
p := pending.Load()
1018-
if p == nil {
1019-
return nil, ErrPendingBlockNotFound
1020-
}
1021-
1022-
expectedParentHash := &felt.Zero
1023-
if head, err := headsHeader(txn); err == nil {
1024-
expectedParentHash = head.Hash
1025-
}
1026-
if p.Block.ParentHash.Equal(expectedParentHash) {
1027-
return p, nil
1028-
}
1029-
1030-
// Since the pending block in the cache is outdated remove it
1031-
pending.Store(nil)
1032-
1033-
return nil, ErrPendingBlockNotFound
1034-
}
1035-
1036-
// Pending returns the pending block from the database
1037-
func (b *Blockchain) Pending() (*Pending, error) {
1038-
b.listener.OnRead("Pending")
1039-
var pending *Pending
1040-
return pending, b.database.View(func(txn db.Transaction) error {
1041-
var err error
1042-
pending, err = pendingBlock(txn)
1043-
return err
1044-
})
1045-
}
1046-
1047-
// PendingState returns the state resulting from execution of the pending block
1048-
func (b *Blockchain) PendingState() (core.StateReader, StateCloser, error) {
1049-
b.listener.OnRead("PendingState")
1050-
txn, err := b.database.NewTransaction(false)
1051-
if err != nil {
1052-
return nil, nil, err
1053-
}
1054-
1055-
pending, err := pendingBlock(txn)
1056-
if err != nil {
1057-
return nil, nil, utils.RunAndWrapOnError(txn.Discard, err)
1058-
}
1059-
1060-
return NewPendingState(pending.StateUpdate.StateDiff, pending.NewClasses, core.NewState(txn)), txn.Discard, nil
1061-
}

0 commit comments

Comments
 (0)