Skip to content
7 changes: 7 additions & 0 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type Reader interface {
BlockHeaderByNumber(number uint64) (header *core.Header, err error)
BlockHeaderByHash(hash *felt.Felt) (header *core.Header, err error)

BlockNumberByHash(hash *felt.Felt) (uint64, error)

TransactionByHash(hash *felt.Felt) (transaction core.Transaction, err error)
TransactionByBlockNumberAndIndex(blockNumber, index uint64) (transaction core.Transaction, err error)
Receipt(hash *felt.Felt) (receipt *core.TransactionReceipt, blockHash *felt.Felt, blockNumber uint64, err error)
Expand Down Expand Up @@ -150,6 +152,11 @@ func (b *Blockchain) BlockHeaderByNumber(number uint64) (*core.Header, error) {
return core.GetBlockHeaderByNumber(b.database, number)
}

func (b *Blockchain) BlockNumberByHash(hash *felt.Felt) (uint64, error) {
b.listener.OnRead("BlockNumberByHash")
return core.GetBlockHeaderNumberByHash(b.database, hash)
}

func (b *Blockchain) BlockByHash(hash *felt.Felt) (*core.Block, error) {
b.listener.OnRead("BlockByHash")
blockNum, err := core.GetBlockHeaderNumberByHash(b.database, hash)
Expand Down
13 changes: 13 additions & 0 deletions mocks/mock_blockchain.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
27 changes: 20 additions & 7 deletions rpc/v6/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,16 @@ func (h *Handler) TransactionByHash(hash felt.Felt) (*Transaction, *jsonrpc.Erro
//
// It follows the specification defined here:
// https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json#L184
func (h *Handler) TransactionByBlockIDAndIndex(id BlockID, txIndex int) (*Transaction, *jsonrpc.Error) {
func (h *Handler) TransactionByBlockIDAndIndex(
id BlockID,
txIndex int,
) (*Transaction, *jsonrpc.Error) {
if txIndex < 0 {
return nil, rpccore.ErrInvalidTxIndex
}

var blockNumber uint64
var err error
if id.Pending {
pending, err := h.PendingData()
if err != nil {
Expand All @@ -500,14 +505,22 @@ func (h *Handler) TransactionByBlockIDAndIndex(id BlockID, txIndex int) (*Transa
}

return AdaptTransaction(pending.GetBlock().Transactions[txIndex]), nil
} else if id.Latest {
header, err := h.bcReader.HeadsHeader()
if err != nil {
return nil, rpccore.ErrBlockNotFound
}
blockNumber = header.Number
} else if id.Hash != nil {
blockNumber, err = h.bcReader.BlockNumberByHash(id.Hash)
if err != nil {
return nil, rpccore.ErrBlockNotFound
}
} else {
blockNumber = id.Number
}

header, rpcErr := h.blockHeaderByID(&id)
if rpcErr != nil {
return nil, rpcErr
}

txn, err := h.bcReader.TransactionByBlockNumberAndIndex(header.Number, uint64(txIndex))
txn, err := h.bcReader.TransactionByBlockNumberAndIndex(blockNumber, uint64(txIndex))
if err != nil {
return nil, rpccore.ErrInvalidTxIndex
}
Expand Down
13 changes: 7 additions & 6 deletions rpc/v6/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
})

t.Run("non-existent block hash", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByHash(gomock.Any()).Return(nil, db.ErrKeyNotFound)
mockReader.EXPECT().BlockNumberByHash(gomock.Any()).Return(uint64(0), db.ErrKeyNotFound)

txn, rpcErr := handler.TransactionByBlockIDAndIndex(
rpc.BlockID{Hash: new(felt.Felt).SetBytes([]byte("random"))}, rand.Int())
Expand All @@ -485,11 +485,13 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
})

t.Run("non-existent block number", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByNumber(gomock.Any()).Return(nil, db.ErrKeyNotFound)
blockNumber := rpc.BlockID{Number: rand.Uint64()}

txn, rpcErr := handler.TransactionByBlockIDAndIndex(rpc.BlockID{Number: rand.Uint64()}, rand.Int())
mockReader.EXPECT().TransactionByBlockNumberAndIndex(blockNumber.Number,
gomock.Any()).Return(nil, errors.New("invalid index"))
txn, rpcErr := handler.TransactionByBlockIDAndIndex(blockNumber, rand.Int())
assert.Nil(t, txn)
assert.Equal(t, rpccore.ErrBlockNotFound, rpcErr)
assert.Equal(t, rpccore.ErrInvalidTxIndex, rpcErr)
})

t.Run("negative index", func(t *testing.T) {
Expand Down Expand Up @@ -533,7 +535,7 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - hash", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByHash(latestBlockHash).Return(latestBlock.Header, nil)
mockReader.EXPECT().BlockNumberByHash(latestBlockHash).Return(latestBlock.Number, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(uint64(latestBlockNumber),
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand All @@ -555,7 +557,6 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - number", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByNumber(uint64(latestBlockNumber)).Return(latestBlock.Header, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(uint64(latestBlockNumber),
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand Down
28 changes: 20 additions & 8 deletions rpc/v7/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,12 +392,16 @@ func adaptRPCTxToFeederTx(rpcTx *Transaction) *starknet.Transaction {
//
// It follows the specification defined here:
// https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json#L184
func (h *Handler) TransactionByBlockIDAndIndex(id BlockID, txIndex int) (*Transaction, *jsonrpc.Error) {
func (h *Handler) TransactionByBlockIDAndIndex(
id BlockID, txIndex int,
) (*Transaction, *jsonrpc.Error) {
if txIndex < 0 {
return nil, rpccore.ErrInvalidTxIndex
}

if id.Pending {
var blockNumber uint64
var err error
if id.IsPending() {
pending, err := h.PendingData()
if err != nil {
return nil, rpccore.ErrBlockNotFound
Expand All @@ -408,14 +412,22 @@ func (h *Handler) TransactionByBlockIDAndIndex(id BlockID, txIndex int) (*Transa
}

return AdaptTransaction(pending.GetBlock().Transactions[txIndex]), nil
} else if id.IsLatest() {
header, err := h.bcReader.HeadsHeader()
if err != nil {
return nil, rpccore.ErrBlockNotFound
}
blockNumber = header.Number
} else if id.Hash != nil {
blockNumber, err = h.bcReader.BlockNumberByHash(id.Hash)
if err != nil {
return nil, rpccore.ErrBlockNotFound
}
} else {
blockNumber = id.Number
}

header, rpcErr := h.blockHeaderByID(&id)
if rpcErr != nil {
return nil, rpcErr
}

txn, err := h.bcReader.TransactionByBlockNumberAndIndex(header.Number, uint64(txIndex))
txn, err := h.bcReader.TransactionByBlockNumberAndIndex(blockNumber, uint64(txIndex))
if err != nil {
return nil, rpccore.ErrInvalidTxIndex
}
Expand Down
11 changes: 6 additions & 5 deletions rpc/v7/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,22 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
})

t.Run("non-existent block hash", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByHash(gomock.Any()).Return(nil, db.ErrKeyNotFound)
mockReader.EXPECT().BlockNumberByHash(gomock.Any()).Return(uint64(0), db.ErrKeyNotFound)

txn, rpcErr := handler.TransactionByBlockIDAndIndex(
rpc.BlockID{Hash: new(felt.Felt).SetBytes([]byte("random"))}, rand.Int())

assert.Nil(t, txn)
assert.Equal(t, rpccore.ErrBlockNotFound, rpcErr)
})

t.Run("non-existent block number", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByNumber(gomock.Any()).Return(nil, db.ErrKeyNotFound)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(gomock.Any(),
gomock.Any()).Return(nil, errors.New("invalid index"))

txn, rpcErr := handler.TransactionByBlockIDAndIndex(rpc.BlockID{Number: rand.Uint64()}, rand.Int())
assert.Nil(t, txn)
assert.Equal(t, rpccore.ErrBlockNotFound, rpcErr)
assert.Equal(t, rpccore.ErrInvalidTxIndex, rpcErr)
})

t.Run("negative index", func(t *testing.T) {
Expand Down Expand Up @@ -107,7 +109,7 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - hash", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByHash(latestBlockHash).Return(latestBlock.Header, nil)
mockReader.EXPECT().BlockNumberByHash(latestBlockHash).Return(latestBlock.Number, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(uint64(latestBlockNumber),
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand All @@ -134,7 +136,6 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - number", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByNumber(uint64(latestBlockNumber)).Return(latestBlock.Header, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(uint64(latestBlockNumber),
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand Down
24 changes: 19 additions & 5 deletions rpc/v8/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,10 @@ func (h *Handler) TransactionByBlockIDAndIndex(
return nil, rpccore.ErrInvalidTxIndex
}

if blockID.IsPending() {
var blockNumber uint64
var err error
switch blockID.Type() {
case pending:
pending, err := h.PendingData()
if err != nil {
return nil, rpccore.ErrBlockNotFound
Expand All @@ -520,14 +523,25 @@ func (h *Handler) TransactionByBlockIDAndIndex(
}

return AdaptTransaction(pending.GetBlock().Transactions[txIndex]), nil
case latest:
header, err := h.bcReader.HeadsHeader()
if err != nil {
return nil, rpccore.ErrBlockNotFound
}
blockNumber = header.Number
case hash:
blockNumber, err = h.bcReader.BlockNumberByHash(blockID.Hash())
case number:
blockNumber = blockID.Number()
default:
panic("unknown block type id")
}

header, rpcErr := h.blockHeaderByID(blockID)
if rpcErr != nil {
return nil, rpcErr
if err != nil {
return nil, rpccore.ErrBlockNotFound
}

txn, err := h.bcReader.TransactionByBlockNumberAndIndex(header.Number, uint64(txIndex))
txn, err := h.bcReader.TransactionByBlockNumberAndIndex(blockNumber, uint64(txIndex))
if err != nil {
return nil, rpccore.ErrInvalidTxIndex
}
Expand Down
10 changes: 5 additions & 5 deletions rpc/v8/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
})

t.Run("non-existent block hash", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByHash(gomock.Any()).Return(nil, db.ErrKeyNotFound)
mockReader.EXPECT().BlockNumberByHash(gomock.Any()).Return(uint64(0), db.ErrKeyNotFound)

blockID := blockIDHash(t, new(felt.Felt).SetBytes([]byte("random")))
txn, rpcErr := handler.TransactionByBlockIDAndIndex(&blockID, rand.Int())
Expand All @@ -485,12 +485,13 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
})

t.Run("non-existent block number", func(t *testing.T) {
mockReader.EXPECT().BlockHeaderByNumber(gomock.Any()).Return(nil, db.ErrKeyNotFound)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(gomock.Any(),
gomock.Any()).Return(nil, errors.New("invalid index"))

blockID := blockIDNumber(t, rand.Uint64())
txn, rpcErr := handler.TransactionByBlockIDAndIndex(&blockID, rand.Int())
assert.Nil(t, txn)
assert.Equal(t, rpccore.ErrBlockNotFound, rpcErr)
assert.Equal(t, rpccore.ErrInvalidTxIndex, rpcErr)
})

t.Run("negative index", func(t *testing.T) {
Expand Down Expand Up @@ -537,7 +538,7 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - hash", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByHash(latestBlockHash).Return(latestBlock.Header, nil)
mockReader.EXPECT().BlockNumberByHash(latestBlockHash).Return(latestBlock.Number, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(latestBlockNumber,
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand All @@ -560,7 +561,6 @@ func TestTransactionByBlockIdAndIndex(t *testing.T) {
t.Run("blockID - number", func(t *testing.T) {
index := rand.Intn(int(latestBlock.TransactionCount))

mockReader.EXPECT().BlockHeaderByNumber(latestBlockNumber).Return(latestBlock.Header, nil)
mockReader.EXPECT().TransactionByBlockNumberAndIndex(latestBlockNumber,
uint64(index)).DoAndReturn(func(number, index uint64) (core.Transaction, error) {
return latestBlock.Transactions[index], nil
Expand Down
31 changes: 26 additions & 5 deletions rpc/v9/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,10 @@ func (h *Handler) TransactionByBlockIDAndIndex(
return nil, rpccore.ErrInvalidTxIndex
}

if blockID.IsPreConfirmed() {
var blockNumber uint64
var err error
switch blockID.Type() {
case preConfirmed:
pending, err := h.PendingData()
if err != nil {
return nil, rpccore.ErrBlockNotFound
Expand All @@ -548,14 +551,32 @@ func (h *Handler) TransactionByBlockIDAndIndex(
}

return AdaptTransaction(pending.GetBlock().Transactions[txIndex]), nil
case latest:
header, err := h.bcReader.HeadsHeader()
if err != nil {
return nil, rpccore.ErrBlockNotFound
Comment thread
brbrr marked this conversation as resolved.
}
blockNumber = header.Number
case hash:
blockNumber, err = h.bcReader.BlockNumberByHash(blockID.Hash())
case number:
blockNumber = blockID.Number()
case l1Accepted:
var l1Head core.L1Head
l1Head, err = h.bcReader.L1Head()
if err != nil {
break
}
blockNumber = l1Head.BlockNumber
default:
panic("unknown block type id")
}

header, rpcErr := h.blockHeaderByID(blockID)
if rpcErr != nil {
return nil, rpcErr
if err != nil {
return nil, rpccore.ErrBlockNotFound
}

txn, err := h.bcReader.TransactionByBlockNumberAndIndex(header.Number, uint64(txIndex))
txn, err := h.bcReader.TransactionByBlockNumberAndIndex(blockNumber, uint64(txIndex))
Comment thread
brbrr marked this conversation as resolved.
if err != nil {
return nil, rpccore.ErrInvalidTxIndex
}
Expand Down
Loading
Loading