Skip to content

Commit

Permalink
implement some tx methods on statev2 (0xPolygonHermez#825)
Browse files Browse the repository at this point in the history
  • Loading branch information
tclemos authored Jun 30, 2022
1 parent 9e1897d commit 91e507d
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 11 deletions.
23 changes: 23 additions & 0 deletions db/migrations/0002.sql
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,26 @@ CREATE TABLE statev2.sync_info

-- Insert default values into sync_info table
INSERT INTO statev2.sync_info (last_batch_num_seen, last_batch_num_consolidated, init_sync_batch)VALUES (0, 0, 0);

CREATE TABLE statev2.receipt
(
tx_hash VARCHAR NOT NULL PRIMARY KEY REFERENCES statev2.transaction (hash) ON DELETE CASCADE,
type integer,
post_state VARCHAR,
status BIGINT,
cumulative_gas_used BIGINT,
gas_used BIGINT,
contract_address VARCHAR
);

CREATE TABLE statev2.log
(
tx_hash VARCHAR NOT NULL PRIMARY KEY REFERENCES statev2.transaction (hash) ON DELETE CASCADE,
log_index integer,
address VARCHAR NOT NULL,
data VARCHAR,
topic0 VARCHAR NOT NULL,
topic1 VARCHAR,
topic2 VARCHAR,
topic3 VARCHAR
);
205 changes: 200 additions & 5 deletions statev2/pgstatestorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ const (
getNextForcedBatchesSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, sequencer, batch_num, block_num FROM statev2.forced_batch WHERE batch_num IS NULL LIMIT $1"
addBatchNumberInForcedBatchSQL = "UPDATE statev2.forced_batch SET batch_num = $2 WHERE forced_batch_num = $1"
getL2BlockByNumberSQL = "SELECT l2_block_num, encoded, header, uncles, received_at from statev2.transaction WHERE batch_num = $1"
getTransactionByHashSQL = "SELECT transaction.encoded FROM statev2.transaction WHERE hash = $1"
getReceiptSQL = "SELECT r.tx_hash, r.type, r.post_state, r.status, r.cumulative_gas_used, r.gas_used, r.contract_address, t.encoded, t.l2_block_num, b.block_hash FROM statev2.receipt r INNER JOIN statev2.transaction t ON t.hash = r.tx_hash INNER JOIN statev2.l2block b ON b.block_num = t.l2_block_num WHERE r.tx_hash = $1"
getTransactionByBlockHashAndIndexSQL = "SELECT t.encoded FROM statev2.transaction t INNER JOIN statev2.l2block b ON t.l2_block_num = b.batch_num WHERE b.block_hash = $1 AND 0 = $2"
getTransactionByBlockNumberAndIndexSQL = "SELECT t.encoded FROM statev2.transaction t WHERE t.l2_block_num = $1 AND 0 = $2"
getBlockTransactionCountByHashSQL = "SELECT COUNT(*) FROM statev2.transaction t INNER JOIN statev2.l2block b ON b.block_num = t.l2_block_num WHERE b.block_hash = $1"
getBlockTransactionCountByNumberSQL = "SELECT COUNT(*) FROM state.transaction t WHERE t.l2_block_num = $1"
getTransactionLogsSQL = "SELECT t.l2_block_num, b.block_hash, l.tx_hash, l.log_index, l.address, l.data, l.topic0, l.topic1, l.topic2, l.topic3 FROM state.log l INNER JOIN statev2.transaction t ON t.hash = l.tx_hash INNER JOIN statev2.l2block b ON b.block_num = t.l2_block_num WHERE transaction_hash = $1"
addL2BlockSQL = "INSERT INTO statev2.l2block (block_num, block_hash, parent_hash, state_root, received_at) VALUES ($1, $2, $3, $4, $5)"
)

Expand Down Expand Up @@ -473,19 +480,207 @@ func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber ui

block.Transactions = make([]*types.Transaction, 1)

b, err := hex.DecodeHex(encoded)
tx, err := decodeTx(encoded)
if err != nil {
return nil, err
}

tx := new(types.Transaction)
if err := tx.UnmarshalBinary(b); err != nil {
block.Transactions[0] = tx

return &block, nil
}

// GetTransactionByHash gets a transaction accordingly to the provided transaction hash
func (p *PostgresStorage) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) {
var encoded string
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getTransactionByHashSQL, transactionHash).Scan(&encoded)

if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
} else if err != nil {
return nil, err
}

block.Transactions[0] = tx
tx, err := decodeTx(encoded)
if err != nil {
return nil, err
}

return &block, nil
return tx, nil
}

// GetTransactionReceipt gets a transaction receipt accordingly to the provided transaction hash
func (p *PostgresStorage) GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Receipt, error) {
var encodedTx string
var l2BlockNum uint64
var l2BlockHash string

receipt := types.Receipt{}
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getReceiptSQL, transactionHash).
Scan(&receipt.TxHash,
&receipt.Type,
&receipt.PostState,
&receipt.Status,
&receipt.CumulativeGasUsed,
&receipt.GasUsed,
&receipt.ContractAddress,
&encodedTx,
&l2BlockNum,
&l2BlockHash,
)

if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
} else if err != nil {
return nil, err
}

logs, err := p.getTransactionLogs(ctx, transactionHash, dbTx)
if !errors.Is(err, pgx.ErrNoRows) && err != nil {
return nil, err
}

receipt.BlockNumber = big.NewInt(0).SetUint64(l2BlockNum)
receipt.BlockHash = common.HexToHash(l2BlockHash)
receipt.TransactionIndex = 0

receipt.Logs = logs
receipt.Bloom = types.CreateBloom(types.Receipts{&receipt})

return &receipt, nil
}

// GetTransactionByBlockHashAndIndex gets a transaction accordingly to the block hash and transaction index provided.
// since we only have a single transaction per l2 block, any index different from 0 will return a not found result
func (p *PostgresStorage) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) {
var encoded string
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getTransactionByBlockHashAndIndexSQL, blockHash.Hex(), index).Scan(&encoded)
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
} else if err != nil {
return nil, err
}

tx, err := decodeTx(encoded)
if err != nil {
return nil, err
}

return tx, nil
}

// GetTransactionByBlockNumberAndIndex gets a transaction accordingly to the block number and transaction index provided.
// since we only have a single transaction per l2 block, any index different from 0 will return a not found result
func (p *PostgresStorage) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) {
var encoded string
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getTransactionByBlockNumberAndIndexSQL, blockNumber, index).Scan(&encoded)
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
} else if err != nil {
return nil, err
}

tx, err := decodeTx(encoded)
if err != nil {
return nil, err
}

return tx, nil
}

// GetBlockTransactionCountByHash returns the number of transactions related to the provided block hash
func (p *PostgresStorage) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash, dbTx pgx.Tx) (uint64, error) {
var count uint64
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getBlockTransactionCountByHashSQL, blockHash.Hex()).Scan(&count)
if err != nil {
return 0, err
}
return count, nil
}

// GetBlockTransactionCountByNumber returns the number of transactions related to the provided block number
func (p *PostgresStorage) GetBlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) {
var count uint64
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getBlockTransactionCountByNumberSQL, blockNumber).Scan(&count)
if err != nil {
return 0, err
}
return count, nil
}

// getTransactionLogs returns the logs of a transaction by transaction hash
func (p *PostgresStorage) getTransactionLogs(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) ([]*types.Log, error) {
q := p.getExecQuerier(dbTx)
rows, err := q.Query(ctx, getTransactionLogsSQL, transactionHash)
if !errors.Is(err, pgx.ErrNoRows) && err != nil {
return nil, err
}
defer rows.Close()

logs := make([]*types.Log, 0, len(rows.RawValues()))

for rows.Next() {
var log types.Log
var txHash, logAddress, logData, topic0 string
var topic1, topic2, topic3 *string

err := rows.Scan(
&log.BlockNumber,
&log.BlockHash,
&txHash,
&log.Index,
&logAddress,
&logData,
&topic0,
&topic1,
&topic2,
&topic3)
if err != nil {
return nil, err
}

log.TxHash = common.HexToHash(txHash)
log.Address = common.HexToAddress(logAddress)
log.TxIndex = uint(0)
log.Data = []byte(logData)

log.Topics = []common.Hash{common.HexToHash(topic0)}
if topic1 != nil {
log.Topics = append(log.Topics, common.HexToHash(*topic1))
}

if topic2 != nil {
log.Topics = append(log.Topics, common.HexToHash(*topic2))
}

if topic3 != nil {
log.Topics = append(log.Topics, common.HexToHash(*topic3))
}

logs = append(logs, &log)
}

return logs, nil
}

// decodeTx decodes a string rlp tx representation into a types.Transaction instance
func decodeTx(encodedTx string) (*types.Transaction, error) {
b, err := hex.DecodeHex(encodedTx)
if err != nil {
return nil, err
}

tx := new(types.Transaction)
if err := tx.UnmarshalBinary(b); err != nil {
return nil, err
}
return tx, nil
}

// AddL2Block adds a new L2 block to the State Store
Expand Down
12 changes: 6 additions & 6 deletions statev2/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,11 @@ func (s *State) GetLastConsolidatedBlockNumber(ctx context.Context, dbTx pgx.Tx)
}

func (s *State) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) {
panic("not implemented yet")
return s.PostgresStorage.GetTransactionByHash(ctx, transactionHash, dbTx)
}

func (s *State) GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Receipt, error) {
panic("not implemented yet")
return s.PostgresStorage.GetTransactionReceipt(ctx, transactionHash, dbTx)
}

func (s *State) GetLastBlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) {
Expand All @@ -479,23 +479,23 @@ func (s *State) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (SyncingInfo, e
}

func (s *State) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) {
panic("not implemented yet")
return s.PostgresStorage.GetTransactionByBlockHashAndIndex(ctx, blockHash, index, dbTx)
}

func (s *State) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) {
panic("not implemented yet")
return s.PostgresStorage.GetTransactionByBlockNumberAndIndex(ctx, blockNumber, index, dbTx)
}

func (s *State) GetBlockHeader(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Header, error) {
panic("not implemented yet")
}

func (s *State) GetBlockTransactionCountByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (uint64, error) {
panic("not implemented yet")
return s.PostgresStorage.GetBlockTransactionCountByHash(ctx, hash, dbTx)
}

func (s *State) GetBlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) {
panic("not implemented yet")
return s.PostgresStorage.GetBlockTransactionCountByNumber(ctx, blockNumber, dbTx)
}

func (s *State) GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*types.Log, error) {
Expand Down

0 comments on commit 91e507d

Please sign in to comment.