You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
8.7 KiB
225 lines
8.7 KiB
defmodule Explorer.Repo.Migrations.CreateTransactions do
|
|
use Ecto.Migration
|
|
|
|
def change do
|
|
create table(:transactions, primary_key: false) do
|
|
# `null` when a pending transaction
|
|
add(:cumulative_gas_used, :numeric, precision: 100, null: true)
|
|
|
|
# `null` before internal transactions are fetched or if no error in those internal transactions
|
|
add(:error, :string, null: true)
|
|
|
|
add(:gas, :numeric, precision: 100, null: false)
|
|
add(:gas_price, :numeric, precision: 100, null: false)
|
|
|
|
# `null` when a pending transaction
|
|
add(:gas_used, :numeric, precision: 100, null: true)
|
|
|
|
add(:hash, :bytea, null: false, primary_key: true)
|
|
|
|
# `null` when a pending transaction
|
|
add(:index, :integer, null: true)
|
|
|
|
add(:input, :bytea, null: false)
|
|
|
|
# `null` when `internal_transactions` has never been fetched
|
|
add(:internal_transactions_indexed_at, :utc_datetime_usec, null: true)
|
|
|
|
add(:nonce, :integer, null: false)
|
|
add(:r, :numeric, precision: 100, null: false)
|
|
add(:s, :numeric, precision: 100, null: false)
|
|
|
|
# `null` when a pending transaction
|
|
add(:status, :integer, null: true)
|
|
|
|
add(:v, :integer, null: false)
|
|
add(:value, :numeric, precision: 100, null: false)
|
|
|
|
timestamps(null: false, type: :utc_datetime_usec)
|
|
|
|
# `null` when a pending transaction
|
|
add(:block_hash, references(:blocks, column: :hash, on_delete: :delete_all, type: :bytea), null: true)
|
|
|
|
# `null` when a pending transaction
|
|
# denormalized from `blocks.number` to improve `Explorer.Chain.recent_collated_transactions/0` performance
|
|
add(:block_number, :integer, null: true)
|
|
|
|
add(:from_address_hash, references(:addresses, column: :hash, on_delete: :delete_all, type: :bytea), null: false)
|
|
# `null` when it is a contract creation transaction
|
|
add(:to_address_hash, references(:addresses, column: :hash, on_delete: :delete_all, type: :bytea), null: true)
|
|
add(:created_contract_address_hash, references(:addresses, column: :hash, type: :bytea), null: true)
|
|
end
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:collated_block_number,
|
|
check: "block_hash IS NULL OR block_number IS NOT NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:collated_cumalative_gas_used,
|
|
check: "block_hash IS NULL OR cumulative_gas_used IS NOT NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:collated_gas_used,
|
|
check: "block_hash IS NULL OR gas_used IS NOT NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:collated_index,
|
|
check: "block_hash IS NULL OR index IS NOT NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:status,
|
|
# 0 - NULL
|
|
# 1 - NOT NULL
|
|
#
|
|
# | block_hash | internal_transactions_indexed_at | status | OK | description
|
|
# |------------|----------------------------------|--------|----|------------
|
|
# | 0 | 0 | 0 | 1 | pending
|
|
# | 0 | 0 | 1 | 0 | pending with status
|
|
# | 0 | 1 | 0 | 0 | pending with internal transactions
|
|
# | 0 | 1 | 1 | 0 | pending with internal transactions and status
|
|
# | 1 | 0 | 0 | 1 | pre-byzantium collated transaction without internal transactions
|
|
# | 1 | 0 | 1 | 1 | post-byzantium collated transaction without internal transactions
|
|
# | 1 | 1 | 0 | 0 | pre-byzantium collated transaction with internal transaction without status
|
|
# | 1 | 1 | 1 | 1 | pre- or post-byzantium collated transaction with internal transactions and status
|
|
#
|
|
# [Karnaugh map](https://en.wikipedia.org/wiki/Karnaugh_map)
|
|
# b \ is | 00 | 01 | 11 | 10 |
|
|
# -------|----|----|----|----|
|
|
# 0 | 1 | 0 | 0 | 0 |
|
|
# 1 | 1 | 1 | 1 | 0 |
|
|
#
|
|
# Simplification: ¬i·¬s + b·¬i + b·s
|
|
check: """
|
|
(internal_transactions_indexed_at IS NULL AND status IS NULL) OR
|
|
(block_hash IS NOT NULL AND internal_transactions_indexed_at IS NULL) OR
|
|
(block_hash IS NOT NULL AND status IS NOT NULL)
|
|
"""
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:error,
|
|
# | status | internal_transactions_indexed_at | error | OK | description
|
|
# |--------|----------------------------------|----------|------------|------------
|
|
# | NULL | NULL | NULL | TRUE | pending or pre-byzantium collated
|
|
# | NULL | NULL | NOT NULL | FALSE | error cannot be known before internal transactions are indexed
|
|
# | NULL | NOT NULL | NULL | DON'T CARE | handled by `status` check
|
|
# | NULL | NOT NULL | NOT NULL | FALSE | error cannot be set unless status is known to be error (`0`)
|
|
# | 0 | NULL | NULL | TRUE | post-byzantium before internal transactions indexed
|
|
# | 0 | NULL | NOT NULL | FALSE | error cannot be set unless internal transactions are indexed
|
|
# | 0 | NOT NULL | NULL | FALSE | error MUST be set when status is error
|
|
# | 0 | NOT NULL | NOT NULL | TRUE | error is set when status is error
|
|
# | 1 | NULL | NULL | TRUE | post-byzantium before internal transactions indexed
|
|
# | 1 | NULL | NOT NULL | FALSE | error cannot be set when status is ok
|
|
# | 1 | NOT NULL | NULL | TRUE | error is not set when status is ok
|
|
# | 1 | NOT NULL | NOT NULL | FALSE | error cannot be set when status is ok
|
|
#
|
|
# Karnaugh map
|
|
# s \ ie | NULL, NULL | NULL, NOT NULL | NOT NULL, NOT NULL | NOT NULL, NULL |
|
|
# -------|------------|----------------|--------------------|----------------|
|
|
# NULL | TRUE | FALSE | FALSE | DON'T CARE |
|
|
# 0 | TRUE | FALSE | TRUE | FALSE |
|
|
# 1 | TRUE | FALSE | FALSE | TRUE |
|
|
#
|
|
check: """
|
|
(internal_transactions_indexed_at IS NULL AND error IS NULL) OR
|
|
(status = 0 AND internal_transactions_indexed_at IS NOT NULL AND error IS NOT NULL) OR
|
|
(status != 0 AND internal_transactions_indexed_at IS NOT NULL AND error IS NULL)
|
|
"""
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:pending_block_number,
|
|
check: "block_hash IS NOT NULL OR block_number IS NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:pending_cumalative_gas_used,
|
|
check: "block_hash IS NOT NULL OR cumulative_gas_used IS NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:pending_gas_used,
|
|
check: "block_hash IS NOT NULL OR gas_used IS NULL"
|
|
)
|
|
)
|
|
|
|
create(
|
|
constraint(
|
|
:transactions,
|
|
:pending_index,
|
|
check: "block_hash IS NOT NULL OR index IS NULL"
|
|
)
|
|
)
|
|
|
|
create(index(:transactions, :block_hash))
|
|
|
|
create(index(:transactions, :inserted_at))
|
|
create(index(:transactions, :updated_at))
|
|
|
|
create(index(:transactions, :status))
|
|
|
|
create(
|
|
index(
|
|
:transactions,
|
|
["block_number DESC NULLS FIRST", "index DESC NULLS FIRST"],
|
|
name: "transactions_recent_collated_index"
|
|
)
|
|
)
|
|
|
|
create(
|
|
index(
|
|
:transactions,
|
|
[:from_address_hash, "block_number DESC NULLS FIRST", "index DESC NULLS FIRST", :hash],
|
|
name: "transactions_from_address_hash_recent_collated_index"
|
|
)
|
|
)
|
|
|
|
create(
|
|
index(
|
|
:transactions,
|
|
[:to_address_hash, "block_number DESC NULLS FIRST", "index DESC NULLS FIRST", :hash],
|
|
name: "transactions_to_address_hash_recent_collated_index"
|
|
)
|
|
)
|
|
|
|
create(
|
|
index(
|
|
:transactions,
|
|
[:created_contract_address_hash, "block_number DESC NULLS FIRST", "index DESC NULLS FIRST", :hash],
|
|
name: "transactions_created_contract_address_hash_recent_collated_index"
|
|
)
|
|
)
|
|
|
|
create(unique_index(:transactions, [:block_hash, :index]))
|
|
end
|
|
end
|
|
|