Skip to content

Commit

Permalink
fix conflict
Browse files Browse the repository at this point in the history
Signed-off-by: Miles Zhang <[email protected]>
  • Loading branch information
zmcNotafraid committed Nov 14, 2024
2 parents 5ad054a + 82bc987 commit 6f0ebd3
Show file tree
Hide file tree
Showing 17 changed files with 330 additions and 142 deletions.
117 changes: 48 additions & 69 deletions app/controllers/api/v2/scripts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,104 +3,83 @@
module Api
module V2
class ScriptsController < BaseController
before_action :set_page_and_page_size, except: :referring_capacities
before_action :find_script, except: :referring_capacities
before_action :set_page_and_page_size
before_action :set_contracts

def general_info
head :not_found and return if @script.blank? || @contract.blank?
head :not_found and return if @contracts.blank?

expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
# expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
render json: { data: get_script_content }
end

def ckb_transactions
head :not_found and return if @contract.blank?

expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
@ckb_transactions =
if @contract.ckb_transactions_count.zero?
CkbTransaction.none
else
@contract.ckb_transactions.order(block_number: :desc).page(@page).per(@page_size).fast_page
end
head :not_found and return if @contracts.blank?

# expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
@ckb_transaction_ids = @contracts.joins(cell_deps_point_outputs: :cell_dependency).
order("cell_dependencies.block_number DESC, cell_dependencies.tx_index ASC").
pluck("cell_dependencies.ckb_transaction_id").
page(@page).
per(@page_size)
CkbTransaction.where(id: @ckb_transaction_ids).order("block_number DESC, tx_index ASC")
end

def deployed_cells
head :not_found and return if @contract.blank?

expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
@deployed_cells =
if @contract.deployed_cells_count.zero?
CellOutput.none
else
@contract.deployed_cell_outputs.live.page(@page).per(@page_size)
end
head :not_found and return if @contracts.blank?

# expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds

CellOutput.live.where(id: @contracts.map(&:deployed_cell_output_id)).page(@page).per(@page_size)
end

def referring_cells
head :not_found and return if @contract.blank?
head :not_found and return if @contracts.blank?

expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds

if @contract.referring_cells_count.zero?
@referring_cells = CellOutput.none
else
scope = @contract.referring_cell_outputs.live.where.not(block_id: nil)
if params[:args].present?
type_script = TypeScript.find_by(args: params[:args])
scope = scope.where(cell_outputs: { type_script_id: type_script.id })
end
if params[:address_hash].present?
address = Addresses::Explore.run!(key: params[:address_hash])
scope = if address.is_a?(NullAddress)
CellOutput.none
else
scope.where(cell_outputs: { address_id: address.map(&:id) })
end
end
# expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds

@referring_cells = sort_referring_cells(scope).page(@page).per(@page_size)
script_ids = Contract.query_script_ids(@contracts)
scope = CellOutput.live.by_scripts(script_ids[:lock_script], script_ids[:type_script])
if params[:args].present?
type_script = TypeScript.find_by(args: params[:args])
scope = scope.or(CellOutput.where(type_script_id: type_script.id))
end
if params[:address_hash].present?
address = Addresses::Explore.run!(key: params[:address_hash])
scope = scope.where(address_id: address.map(&:id))
end

@referring_cells = sort_referring_cells(scope).page(@page).per(@page_size)
end

private

def get_script_content
deployed_cells = @contract.deployed_cell_outputs
if deployed_cells.present?
deployed_type_script = deployed_cells[0].type_script
if deployed_type_script && deployed_type_script.code_hash == Settings.type_id_code_hash
type_id = deployed_type_script.script_hash
end
@contracts.map do |contract|
{
type_hash: contract.type_hash,
data_hash: contract.data_hash,
is_lock_script: contract.is_lock_script,
is_type_script: contract.is_type_script,
# capacity_of_deployed_cells: contract.total_deployed_cells_capacity,
# capacity_of_referring_cells: contract.total_referring_cells_capacity,
}
end

{
id: type_id,
code_hash: @script.code_hash,
hash_type: @script.hash_type,
script_type: @script.class.to_s,
capacity_of_deployed_cells: @contract.total_deployed_cells_capacity,
capacity_of_referring_cells: @contract.total_referring_cells_capacity,
count_of_transactions: @contract.ckb_transactions_count,
count_of_deployed_cells: @contract.deployed_cells_count,
count_of_referring_cells: @contract.referring_cells_count,
}
end

def set_page_and_page_size
@page = params[:page] || 1
@page_size = params[:page_size] || 10
end

def find_script
@script = TypeScript.find_by(code_hash: params[:code_hash],
hash_type: params[:hash_type])
if @script.blank?
@script = LockScript.find_by(code_hash: params[:code_hash],
hash_type: params[:hash_type])
end
@contract = Contract.find_by(code_hash: params[:code_hash],
hash_type: params[:hash_type])
def set_contracts
@contracts =
case params[:hash_type]
when "data", "data1", "data2"
Contract.where(data_hash: params[:code_hash])
when "type"
Contract.find_by(type_hash: params[:code_hash])
end
end

def sort_referring_cells(records)
Expand Down
111 changes: 98 additions & 13 deletions app/models/cell_dependency.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# this is the ReferringCell model, parse from `cell_deps` of transaction raw hash
class CellDependency < ApplicationRecord
belongs_to :contract, optional: true
belongs_to :ckb_transaction
belongs_to :script
belongs_to :cell_output, foreign_key: "contract_cell_id", class_name: "CellOutput"
enum :dep_type, [:code, :dep_group]
scope :implicit, -> { where(implicit: true) }
scope :explicit, -> { where(implicit: false) }
has_many :cell_deps_point_outputs, foreign_key: :contract_cell_id, primary_key: :contract_cell_id

enum :dep_type, %i[code dep_group]

def self.refresh_implicit
connection.execute "SELECT update_cell_dependencies_implicit();"
Expand All @@ -16,29 +14,116 @@ def to_raw
{
out_point: {
tx_hash: cell_output.tx_hash,
index: cell_output.cell_index
index: cell_output.cell_index,
},
dep_type: dep_type
dep_type:,
}
end

def parse_cell_dpes_from_ckb_transaction(ckb_transaction, cell_deps)
return if cell_deps.blank?

cell_dependencies_attrs = []
cell_deps_out_points_attrs = Set.new
contract_attrs = Set.new

cell_deps.each do |cell_dep|
if cell_dep.is_a?(CKB::Types::CellDep)
cell_dep = cell_dep.to_h.with_indifferent_access
end
case cell_dep["dep_type"]
when "code"
cell_output = CellOutput.find_by_pointer cell_dep["out_point"]["tx_hash"], cell_dep["out_point"]["index"]
cell_dependencies_attrs << {
contract_cell_id: cell_output.id,
dep_type: cell_dep["dep_type"],
ckb_transaction_id: ckb_transaction.id,
block_number: ckb_transaction.block_number,
tx_index: ckb_transaction.tx_index,
}

cell_deps_out_points_attrs << {
tx_hash: cell_dep["out_point"]["tx_hash"],
cell_index: cell_dep["out_point"]["cell_index"],
deployed_cell_output_id: cell_output.id,
contract_cell_id: cell_output.id,
}

contract_attrs <<
{
type_hash: cell_output.type_script&.script_hash,
data_hash: cell_output.data_hash,
deployed_cell_output_id: cell_output.id,
is_type_script: TypeScript.type_script?(cell_output.type_script&.script_hash, cell_output.data_hash),
is_lock_script: LockScript.lock_script?(cell_output.type_script&.script_hash, cell_output.data_hash),
deployed_args: cell_output.type_script&.args,
}

when "dep_group"
# when the type of cell_dep is "dep_group", it means the cell specified by the `out_point` is a list of out points to the actual referred contract cells
mid_cell = CellOutput.find_by_pointer cell_dep["out_point"]["tx_hash"], cell_dep["out_point"]["index"]

cell_dependencies_attrs << {
contract_cell_id: mid_cell.id,
dep_type: cell_dep["dep_type"],
ckb_transaction_id: ckb_transaction.id,
block_number: ckb_transaction.block_number,
tx_index: ckb_transaction.tx_index,
}

binary_data = mid_cell.binary_data
# binary_data = [hex_data[2..-1]].pack("H*")
# parse the actual list of out points from the data field of the cell
out_points_count = binary_data[0, 4].unpack("L<")
# iterate over the out point list and append actual referred contract cells to cell dependencies_attrs
0.upto(out_points_count[0] - 1) do |i|
tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<")
cell_output = CellOutput.find_by_pointer tx_hash, cell_index
cell_deps_out_points_attrs << {
tx_hash:,
cell_index:,
deployed_cell_output_id: cell_output.id,
contract_cell_id: mid_cell.id,
}

contract_attrs <<
{
type_hash: cell_output.type_script&.script_hash,
data_hash: cell_output.data_hash,
is_type_script: TypeScript.type_script?(cell_output.type_script&.script_hash, cell_output.data_hash),
is_lock_script: LockScript.lock_script?(cell_output.type_script&.script_hash, cell_output.data_hash),
deployed_cell_output_id: cell_output.id,
deployed_args: cell_output.type_script&.args,
}
end
end

CellDependency.upsert_all(cell_dependencies_attrs,
unique_by: %i[ckb_transaction_id contract_cell_id])
CellDepsOutPoint.upsert_all(cell_deps_out_points_attrs,
unique_by: %i[contract_cell_id deployed_cell_output_id])
Contract.upsert_all(contract_attrs, unique_by: %i[deployed_cell_output_id], update_only: %i[is_lock_script is_type_script])
end
end
end

# == Schema Information
#
# Table name: cell_dependencies
#
# id :bigint not null, primary key
# contract_id :bigint
# ckb_transaction_id :bigint not null
# dep_type :integer
# contract_cell_id :bigint not null
# script_id :bigint
# implicit :boolean default(TRUE), not null
# contract_id :bigint
# implicit :boolean
# block_number :bigint
# tx_index :integer
#
# Indexes
#
# cell_deps_tx_cell_idx (ckb_transaction_id,contract_cell_id) UNIQUE
# index_cell_dependencies_on_contract_cell_id (contract_cell_id)
# index_cell_dependencies_on_contract_id (contract_id)
# index_cell_dependencies_on_script_id (script_id)
# cell_deps_tx_cell_idx (ckb_transaction_id,contract_cell_id) UNIQUE
# index_cell_dependencies_on_block_number_and_tx_index (block_number,tx_index)
# index_cell_dependencies_on_contract_cell_id (contract_cell_id)
#
21 changes: 21 additions & 0 deletions app/models/cell_deps_out_point.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class CellDepsOutPoint < ApplicationRecord
belongs_to :cell_dependency, foreign_key: :contract_cell_id, primary_key: :contract_cell_id
belongs_to :contract, foreign_key: :deployed_cell_id, primary_key: :deployed_cell_id
end

# == Schema Information
#
# Table name: cell_deps_out_points
#
# id :bigint not null, primary key
# tx_hash :binary
# cell_index :integer
# deployed_cell_output_id :bigint
# contract_cell_id :bigint
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_cell_deps_out_points_on_contract_cell_id_deployed_cell_id (contract_cell_id,deployed_cell_output_id) UNIQUE
#
5 changes: 3 additions & 2 deletions app/models/cell_output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class CellOutput < ApplicationRecord
# but one cell may be included by many pending transactions,
# the cell_inputs won't always be the same as `consumed_by`.`cell_inputs`
has_many :cell_inputs, foreign_key: :previous_cell_output_id
belongs_to :deployed_cell, optional: true
has_many :referring_cells
# belongs_to :deployed_cell, optional: true
# has_many :referring_cells
# the block_id is actually the same as ckb_transaction.block_id, must be on chain
# but one cell may be included by pending transactions, so block_id may be null
belongs_to :block, optional: true
Expand Down Expand Up @@ -107,6 +107,7 @@ class CellOutput < ApplicationRecord
scope :occupied, -> {
where.not(type_hash: nil).or(where.not(data_hash: nil))
}
scope :by_scripts, ->(lock_script_ids, type_script_ids) { where("lock_script_id IN (?) AND type_script_id IN (?)", lock_script_ids, type_script_ids) }

before_create :setup_address

Expand Down
4 changes: 2 additions & 2 deletions app/models/ckb_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def header_deps

def cell_deps
_outputs = cell_outputs.order(cell_index: :asc).to_a
cell_dependencies.explicit.includes(:cell_output).to_a.map(&:to_raw)
cell_dependencies.includes(:cell_output).to_a.map(&:to_raw)
end

def income(address)
Expand Down Expand Up @@ -215,7 +215,7 @@ def detailed_message
def to_raw
Rails.cache.fetch([self.class.name, tx_hash, "raw_hash"], expires_in: 1.day) do
_outputs = cell_outputs.order(cell_index: :asc).to_a
cell_deps = cell_dependencies.explicit.includes(:cell_output).to_a
cell_deps = cell_dependencies.includes(:cell_output).to_a

{
hash: tx_hash,
Expand Down
Loading

0 comments on commit 6f0ebd3

Please sign in to comment.