Skip to content

Commit

Permalink
New Tenscan APIs (#1879)
Browse files Browse the repository at this point in the history
* add new APIs required for tenscan and refactor existing code
  • Loading branch information
badgersrus authored Apr 30, 2024
1 parent c2a7b13 commit ac1b90a
Show file tree
Hide file tree
Showing 23 changed files with 849 additions and 98 deletions.
6 changes: 3 additions & 3 deletions go/common/query_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type PublicTransaction struct {

type PublicBatch struct {
SequencerOrderNo *big.Int `json:"sequence"`
Hash []byte `json:"hash"`
Hash string `json:"hash"`
FullHash common.Hash `json:"fullHash"`
Height *big.Int `json:"height"`
TxCount *big.Int `json:"txCount"`
Expand All @@ -65,12 +65,12 @@ type PublicBatchDeprecated struct {

type PublicRollup struct {
ID *big.Int
Hash []byte
Hash string
FirstSeq *big.Int
LastSeq *big.Int
Timestamp uint64
Header *RollupHeader
L1Hash []byte
L1Hash string
}

type PublicBlock struct {
Expand Down
29 changes: 27 additions & 2 deletions go/host/rpc/clientapi/client_api_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func (s *ScanAPI) GetTotalContractCount(ctx context.Context) (*big.Int, error) {
return s.host.EnclaveClient().GetTotalContractCount(ctx)
}

// GetTransaction returns the transaction given its hash.
func (s *ScanAPI) GetTransaction(hash gethcommon.Hash) (*common.PublicTransaction, error) {
return s.host.Storage().FetchTransaction(hash)
}

// GetTotalTxCount returns the number of recorded transactions on the network.
func (s *ScanAPI) GetTotalTransactionCount() (*big.Int, error) {
return s.host.Storage().FetchTotalTxCount()
Expand Down Expand Up @@ -65,8 +70,13 @@ func (s *ScanAPI) GetLatestBatch() (*common.BatchHeader, error) {
}

// GetBatchByHeight returns the `BatchHeader` with the given height
func (s *ScanAPI) GetBatchByHeight(height *big.Int) (*common.BatchHeader, error) {
return s.host.Storage().FetchBatchHeaderByHeight(height)
func (s *ScanAPI) GetBatchByHeight(height *big.Int) (*common.PublicBatch, error) {
return s.host.Storage().FetchBatchByHeight(height)
}

// GetRollupBySeqNo returns the `PublicRollup` that contains the batch with the given sequence number
func (s *ScanAPI) GetRollupBySeqNo(seqNo uint64) (*common.PublicRollup, error) {
return s.host.Storage().FetchRollupBySeqNo(seqNo)
}

// GetRollupListing returns a paginated list of Rollups
Expand All @@ -88,3 +98,18 @@ func (s *ScanAPI) GetPublicTransactionData(ctx context.Context, pagination *comm
func (s *ScanAPI) GetBlockListing(pagination *common.QueryPagination) (*common.BlockListingResponse, error) {
return s.host.Storage().FetchBlockListing(pagination)
}

// GetRollupByHash returns the public rollup data given its hash
func (s *ScanAPI) GetRollupByHash(rollupHash gethcommon.Hash) (*common.PublicRollup, error) {
return s.host.Storage().FetchRollupByHash(rollupHash)
}

// GetRollupBatches returns the list of batches included in a rollup given its hash
func (s *ScanAPI) GetRollupBatches(rollupHash gethcommon.Hash) (*common.BatchListingResponse, error) {
return s.host.Storage().FetchRollupBatches(rollupHash)
}

// GetBatchTransactions returns the public tx data of all txs present in a rollup given its hash
func (s *ScanAPI) GetBatchTransactions(batchHash gethcommon.Hash) (*common.TransactionListingResponse, error) {
return s.host.Storage().FetchBatchTransactions(batchHash)
}
134 changes: 106 additions & 28 deletions go/host/storage/hostdb/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import (

const (
selectTxCount = "SELECT total FROM transaction_count WHERE id = 1"
selectTxSeqNo = "SELECT full_hash, b_sequence FROM transactions_host WHERE hash = "
selectBatch = "SELECT sequence, full_hash, hash, height, ext_batch FROM batch_host"
selectExtBatch = "SELECT ext_batch FROM batch_host"
selectLatestBatch = "SELECT sequence, full_hash, hash, height, ext_batch FROM batch_host ORDER BY sequence DESC LIMIT 1"
selectTxsAndBatch = "SELECT t.hash FROM transactions_host t JOIN batch_host b ON t.b_sequence = b.sequence WHERE b.full_hash = "
selectBatchSeqByTx = "SELECT b_sequence FROM transactions_host WHERE hash = "
selectTxBySeq = "SELECT hash FROM transactions_host WHERE b_sequence = "
selectTxBySeq = "SELECT full_hash FROM transactions_host WHERE b_sequence = "
selectBatchTxs = "SELECT t.full_hash, b.sequence, b.height, b.ext_batch FROM transactions_host t JOIN batch_host b ON t.b_sequence = b.sequence"
)

// AddBatch adds a batch and its header to the DB
Expand All @@ -41,8 +43,8 @@ func AddBatch(dbtx *dbTransaction, statements *SQLStatements, batch *common.ExtB
}

if len(batch.TxHashes) > 0 {
for _, transaction := range batch.TxHashes {
_, err = dbtx.tx.Exec(statements.InsertTransactions, transaction.Bytes(), batch.SeqNo().Uint64())
for _, txHash := range batch.TxHashes {
_, err = dbtx.tx.Exec(statements.InsertTransactions, truncTo16(txHash), txHash.Bytes(), batch.SeqNo().Uint64())
if err != nil {
return fmt.Errorf("failed to insert transaction with hash: %d", err)
}
Expand All @@ -67,7 +69,7 @@ func AddBatch(dbtx *dbTransaction, statements *SQLStatements, batch *common.ExtB
// GetBatchListing returns latest batches given a pagination.
// For example, page 0, size 10 will return the latest 10 batches.
func GetBatchListing(db HostDB, pagination *common.QueryPagination) (*common.BatchListingResponse, error) {
headBatch, err := GetCurrentHeadBatch(db.GetSQLDB())
headBatch, err := GetCurrentHeadBatch(db)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -98,7 +100,7 @@ func GetBatchListing(db HostDB, pagination *common.QueryPagination) (*common.Bat
// GetBatchListingDeprecated returns latest batches given a pagination.
// For example, page 0, size 10 will return the latest 10 batches.
func GetBatchListingDeprecated(db HostDB, pagination *common.QueryPagination) (*common.BatchListingResponseDeprecated, error) {
headBatch, err := GetCurrentHeadBatch(db.GetSQLDB())
headBatch, err := GetCurrentHeadBatch(db)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -159,8 +161,8 @@ func GetBatchBySequenceNumber(db HostDB, seqNo uint64) (*common.ExtBatch, error)
}

// GetCurrentHeadBatch retrieves the current head batch with the largest sequence number (or height).
func GetCurrentHeadBatch(db *sql.DB) (*common.PublicBatch, error) {
return fetchHeadBatch(db)
func GetCurrentHeadBatch(db HostDB) (*common.PublicBatch, error) {
return fetchHeadBatch(db.GetSQLDB())
}

// GetBatchHeader returns the batch header given the hash.
Expand All @@ -181,8 +183,8 @@ func GetBatchHashByNumber(db HostDB, number *big.Int) (*gethcommon.Hash, error)
}

// GetHeadBatchHeader returns the latest batch header.
func GetHeadBatchHeader(db *sql.DB) (*common.BatchHeader, error) {
batch, err := fetchHeadBatch(db)
func GetHeadBatchHeader(db HostDB) (*common.BatchHeader, error) {
batch, err := fetchHeadBatch(db.GetSQLDB())
if err != nil {
return nil, err
}
Expand All @@ -191,16 +193,15 @@ func GetHeadBatchHeader(db *sql.DB) (*common.BatchHeader, error) {

// GetBatchNumber returns the height of the batch containing the given transaction hash.
func GetBatchNumber(db HostDB, txHash gethcommon.Hash) (*big.Int, error) {
txBytes := txHash.Bytes()
batchHeight, err := fetchBatchNumber(db, txBytes)
batchHeight, err := fetchBatchNumber(db, truncTo16(txHash))
if err != nil {
return nil, err
}
return batchHeight, nil
}

// GetBatchTxs returns the transaction hashes of the batch with the given hash.
func GetBatchTxs(db HostDB, batchHash gethcommon.Hash) ([]gethcommon.Hash, error) {
// GetBatchTxHashes returns the transaction hashes of the batch with the given hash.
func GetBatchTxHashes(db HostDB, batchHash gethcommon.Hash) ([]gethcommon.Hash, error) {
query := selectTxsAndBatch + db.GetSQLStatement().Placeholder
rows, err := db.GetSQLDB().Query(query, batchHash)
if err != nil {
Expand All @@ -226,15 +227,41 @@ func GetBatchTxs(db HostDB, batchHash gethcommon.Hash) ([]gethcommon.Hash, error
}

// GetTotalTxCount returns the total number of batched transactions.
func GetTotalTxCount(db *sql.DB) (*big.Int, error) {
func GetTotalTxCount(db HostDB) (*big.Int, error) {
var totalCount int
err := db.QueryRow(selectTxCount).Scan(&totalCount)
err := db.GetSQLDB().QueryRow(selectTxCount).Scan(&totalCount)
if err != nil {
return nil, fmt.Errorf("failed to retrieve total transaction count: %w", err)
}
return big.NewInt(int64(totalCount)), nil
}

// GetTransaction returns a transaction given its hash
func GetTransaction(db HostDB, hash gethcommon.Hash) (*common.PublicTransaction, error) {
query := selectTxSeqNo + db.GetSQLStatement().Placeholder

var fullHash []byte
var seq int
err := db.GetSQLDB().QueryRow(query, truncTo16(hash)).Scan(&fullHash, &seq)
if err != nil {
return nil, fmt.Errorf("failed to retrieve transaction sequence number: %w", err)
}

batch, err := GetBatchBySequenceNumber(db, uint64(seq))
if err != nil {
return nil, fmt.Errorf("failed to retrieve batch by sequence number: %w", err)
}

tx := &common.PublicTransaction{
TransactionHash: gethcommon.BytesToHash(fullHash),
BatchHeight: batch.Header.Number,
BatchTimestamp: batch.Header.Time,
Finality: common.BatchFinal,
}

return tx, nil
}

// GetPublicBatch returns the batch with the given hash.
func GetPublicBatch(db HostDB, hash common.L2BatchHash) (*common.PublicBatch, error) {
whereQuery := " WHERE b.hash=" + db.GetSQLStatement().Placeholder
Expand All @@ -245,7 +272,7 @@ func GetPublicBatch(db HostDB, hash common.L2BatchHash) (*common.PublicBatch, er
func GetBatchByTx(db HostDB, txHash gethcommon.Hash) (*common.ExtBatch, error) {
var seqNo uint64
query := selectBatchSeqByTx + db.GetSQLStatement().Placeholder
err := db.GetSQLDB().QueryRow(query, txHash).Scan(&seqNo)
err := db.GetSQLDB().QueryRow(query, truncTo16(txHash)).Scan(&seqNo)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, errutil.ErrNotFound
Expand All @@ -262,27 +289,35 @@ func GetBatchByHash(db HostDB, hash common.L2BatchHash) (*common.ExtBatch, error
}

// GetLatestBatch returns the head batch header
func GetLatestBatch(db *sql.DB) (*common.BatchHeader, error) {
headBatch, err := fetchHeadBatch(db)
func GetLatestBatch(db HostDB) (*common.BatchHeader, error) {
headBatch, err := fetchHeadBatch(db.GetSQLDB())
if err != nil {
return nil, fmt.Errorf("failed to fetch head batch: %w", err)
}
return headBatch.Header, nil
}

// GetBatchHeaderByHeight returns the batch header given the height
func GetBatchHeaderByHeight(db HostDB, height *big.Int) (*common.BatchHeader, error) {
whereQuery := " WHERE height=" + db.GetSQLStatement().Placeholder
return fetchBatchHeader(db.GetSQLDB(), whereQuery, height.Uint64())
}

// GetBatchByHeight returns the batch header given the height
func GetBatchByHeight(db HostDB, height *big.Int) (*common.BatchHeader, error) {
func GetBatchByHeight(db HostDB, height *big.Int) (*common.PublicBatch, error) {
whereQuery := " WHERE height=" + db.GetSQLStatement().Placeholder
headBatch, err := fetchBatchHeader(db.GetSQLDB(), whereQuery, height.Uint64())
if err != nil {
return nil, fmt.Errorf("failed to batch header: %w", err)
}
return headBatch, nil
return fetchPublicBatch(db.GetSQLDB(), whereQuery, height.Uint64())
}

// GetBatchTransactions returns the TransactionListingResponse for a given batch hash
func GetBatchTransactions(db HostDB, batchHash gethcommon.Hash) (*common.TransactionListingResponse, error) {
whereQuery := " WHERE b.full_hash=" + db.GetSQLStatement().Placeholder
return fetchBatchTxs(db.GetSQLDB(), whereQuery, batchHash)
}

func fetchBatchHeader(db *sql.DB, whereQuery string, args ...any) (*common.BatchHeader, error) {
var extBatch []byte
query := selectExtBatch + " " + whereQuery
query := selectExtBatch + whereQuery
var err error
if len(args) > 0 {
err = db.QueryRow(query, args...).Scan(&extBatch)
Expand Down Expand Up @@ -333,7 +368,7 @@ func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.Publi
var heightInt64 int
var extBatch []byte

query := selectBatch + " " + whereQuery
query := selectBatch + whereQuery

var err error
if len(args) > 0 {
Expand All @@ -355,7 +390,7 @@ func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.Publi

batch := &common.PublicBatch{
SequencerOrderNo: new(big.Int).SetInt64(int64(sequenceInt64)),
Hash: hash,
Hash: bytesToHexString(hash),
FullHash: fullHash,
Height: new(big.Int).SetInt64(int64(heightInt64)),
TxCount: new(big.Int).SetInt64(int64(len(b.TxHashes))),
Expand Down Expand Up @@ -419,7 +454,7 @@ func fetchHeadBatch(db *sql.DB) (*common.PublicBatch, error) {

batch := &common.PublicBatch{
SequencerOrderNo: new(big.Int).SetInt64(int64(sequenceInt64)),
Hash: hash,
Hash: bytesToHexString(hash),
FullHash: fullHash,
Height: new(big.Int).SetInt64(int64(heightInt64)),
TxCount: new(big.Int).SetInt64(int64(len(b.TxHashes))),
Expand Down Expand Up @@ -454,3 +489,46 @@ func fetchTx(db HostDB, seqNo uint64) ([]common.TxHash, error) {

return transactions, nil
}

func fetchBatchTxs(db *sql.DB, whereQuery string, batchHash gethcommon.Hash) (*common.TransactionListingResponse, error) {
query := selectBatchTxs + whereQuery
rows, err := db.Query(query, batchHash)
if err != nil {
return nil, fmt.Errorf("query execution for select batch txs failed: %w", err)
}
defer rows.Close()

var transactions []common.PublicTransaction
for rows.Next() {
var (
fullHash []byte
sequence int
height int
extBatch []byte
)
err := rows.Scan(&fullHash, &sequence, &height, &extBatch)
if err != nil {
return nil, err
}
extBatchDecoded := new(common.ExtBatch)
if err := rlp.DecodeBytes(extBatch, extBatchDecoded); err != nil {
return nil, fmt.Errorf("could not decode batch. Cause: %w", err)
}
transaction := common.PublicTransaction{
TransactionHash: gethcommon.BytesToHash(fullHash),
BatchHeight: big.NewInt(int64(height)),
BatchTimestamp: extBatchDecoded.Header.Time,
Finality: common.BatchFinal,
}
transactions = append(transactions, transaction)
}

if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error looping through transacion rows: %w", err)
}

return &common.TransactionListingResponse{
TransactionsData: transactions,
Total: uint64(len(transactions)),
}, nil
}
Loading

0 comments on commit ac1b90a

Please sign in to comment.