Skip to content

Commit 329cb70

Browse files
authored
Merge pull request #2444 from nervosnetwork/testnet
Deploy to mainnet
2 parents 1978f3d + e5a11d3 commit 329cb70

File tree

11 files changed

+201
-118
lines changed

11 files changed

+201
-118
lines changed

app/controllers/api/v2/nft/transfers_controller.rb

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,18 @@ module V2
33
module NFT
44
class TransfersController < BaseController
55
def index
6-
if params[:collection_id].present?
7-
if /\A\d+\z/.match?(params[:collection_id])
8-
collection = TokenCollection.find params[:collection_id]
9-
else
10-
collection = TokenCollection.find_by_sn params[:collection_id]
11-
end
12-
end
13-
14-
if collection && params[:token_id]
15-
item = collection.items.find_by token_id: params[:token_id]
16-
end
17-
18-
if item
19-
scope = item.transfers
20-
elsif collection
21-
scope = collection.transfers
22-
else
23-
scope = TokenTransfer.all
24-
end
6+
scope = TokenTransfer.all
257

26-
if params[:from]
27-
scope = scope.where(from: find_address(params[:from]))
28-
end
29-
if params[:to]
30-
scope = scope.where(to: find_address(params[:to]))
31-
end
32-
if params[:address_hash]
33-
address = find_address(params[:address_hash])
34-
scope = scope.where(from: address).or(scope.where(to: address))
35-
end
36-
if params[:transfer_action]
37-
scope = scope.where(action: params[:transfer_action])
38-
end
39-
if params[:tx_hash]
40-
scope = scope.includes(:ckb_transaction).where(ckb_transaction: { tx_hash: params[:tx_hash] })
8+
if params[:collection_id].present?
9+
collection = find_collection(params[:collection_id])
10+
scope = collection.present? ? filtered_by_token_id(collection) : TokenTransfer.none
4111
end
4212

13+
scope = apply_filters(scope)
4314
scope = scope.order(transaction_id: :desc)
4415
pagy, token_transfers = pagy(scope)
4516

46-
render json: {
47-
data: token_transfers,
48-
pagination: pagy
49-
}
17+
render json: { data: token_transfers, pagination: pagy }
5018
end
5119

5220
def show
@@ -64,6 +32,36 @@ def download_csv
6432

6533
private
6634

35+
def find_collection(collection_id)
36+
if /\A\d+\z/.match?(collection_id)
37+
TokenCollection.find_by(id: collection_id)
38+
else
39+
TokenCollection.find_by(sn: collection_id)
40+
end
41+
end
42+
43+
def filtered_by_token_id(collection)
44+
if params[:token_id].present?
45+
item = collection.items.find_by(token_id: params[:token_id])
46+
item.nil? ? TokenTransfer.none : item.transfers
47+
else
48+
collection.transfers
49+
end
50+
end
51+
52+
def apply_filters(scope)
53+
scope = scope.where(from: find_address(params[:from])) if params[:from].present?
54+
scope = scope.where(to: find_address(params[:to])) if params[:to].present?
55+
if params[:address_hash].present?
56+
address = find_address(params[:address_hash])
57+
scope = scope.where(from: address).or(scope.where(to: address))
58+
end
59+
scope = scope.where(action: params[:transfer_action]) if params[:transfer_action].present?
60+
scope = scope.includes(:ckb_transaction).where(ckb_transaction: { tx_hash: params[:tx_hash] }) if params[:tx_hash].present?
61+
62+
scope
63+
end
64+
6765
def find_address(address_hash)
6866
Address.find_by_address_hash(address_hash)
6967
end

app/controllers/api/v2/scripts_controller.rb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,19 @@ def ckb_transactions
1818

1919
contract_ids = @contracts.map { |contract| contract.id }
2020
contract_cell_ids = CellDepsOutPoint.list_contract_cell_ids_by_contract(contract_ids)
21-
base_query = CkbTransaction.joins(:cell_dependencies).
22-
where(cell_dependencies: { contract_cell_id: contract_cell_ids }).
23-
order("cell_dependencies.block_number DESC, cell_dependencies.tx_index DESC").
24-
limit(Settings.query_default_limit)
21+
restrict_query =
22+
if params[:restrict] == "true"
23+
CkbTransaction.joins(:cell_dependencies).
24+
where(cell_dependencies: { contract_cell_id: contract_cell_ids, is_used: true })
25+
else
26+
CkbTransaction.joins(:cell_dependencies).
27+
where(cell_dependencies: { contract_cell_id: contract_cell_ids })
28+
end
29+
30+
base_query =
31+
restrict_query.
32+
order("cell_dependencies.block_number DESC, cell_dependencies.tx_index DESC").
33+
limit(Settings.query_default_limit)
2534
@ckb_transactions = CkbTransaction.from("(#{base_query.to_sql}) AS ckb_transactions").
2635
order("block_number DESC, tx_index DESC").
2736
page(@page).

app/models/cell_dependency.rb

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
# this is the ReferringCell model, parse from `cell_deps` of transaction raw hash
21
class CellDependency < ApplicationRecord
32
belongs_to :ckb_transaction
43
belongs_to :cell_output, foreign_key: "contract_cell_id", class_name: "CellOutput"
54
belongs_to :cell_deps_out_point, foreign_key: :contract_cell_id, primary_key: :contract_cell_id, optional: true
65

76
enum :dep_type, %i[code dep_group]
87

9-
def self.refresh_implicit
10-
connection.execute "SELECT update_cell_dependencies_implicit();"
11-
end
12-
138
def to_raw
149
{
1510
out_point: {
@@ -26,22 +21,18 @@ def to_raw
2621
# Table name: cell_dependencies
2722
#
2823
# id :bigint not null, primary key
29-
# contract_id :bigint
3024
# ckb_transaction_id :bigint not null
3125
# dep_type :integer
3226
# contract_cell_id :bigint not null
33-
# script_id :bigint
34-
# implicit :boolean default(TRUE), not null
3527
# block_number :bigint
3628
# tx_index :integer
3729
# contract_analyzed :boolean default(FALSE)
30+
# is_used :boolean default(TRUE)
3831
#
3932
# Indexes
4033
#
4134
# index_cell_dependencies_on_block_number_and_tx_index (block_number,tx_index)
4235
# index_cell_dependencies_on_contract_analyzed (contract_analyzed)
43-
# index_cell_dependencies_on_contract_id (contract_id)
44-
# index_cell_dependencies_on_script_id (script_id)
4536
# index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type (ckb_transaction_id,contract_cell_id,dep_type) UNIQUE
4637
# index_on_cell_dependencies_contract_cell_block_tx (contract_cell_id,block_number DESC,tx_index DESC)
4738
#

app/workers/analyze_contract_from_cell_dependency_worker.rb

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ def perform
1010
cell_deps_attrs = Set.new
1111
contract_roles = Hash.new { |hash, key| hash[key] = {} }
1212

13-
# 加载未分析的依赖数据
1413
dependencies = load_unanalyzed_dependencies
1514

16-
# 按事务分组并逐组处理
1715
dependencies.each do |ckb_transaction_id, cell_deps|
1816
ckb_transaction = CkbTransaction.find(ckb_transaction_id)
1917
lock_scripts, type_scripts = analyze_scripts(ckb_transaction)
@@ -29,61 +27,62 @@ def perform
2927
)
3028
end
3129

32-
# 持久化数据
3330
save_cell_deps_out_points(cell_deps_out_points_attrs)
3431
save_contracts(contract_attrs, contract_roles)
3532
save_cell_dependencies(cell_deps_attrs)
3633
end
3734

3835
private
3936

40-
# 加载未分析的依赖数据
4137
def load_unanalyzed_dependencies
4238
CellDependency.where(contract_analyzed: false).
4339
where.not(block_number: nil).
4440
limit(200).
4541
group_by(&:ckb_transaction_id)
4642
end
4743

48-
# 分析脚本
4944
def analyze_scripts(ckb_transaction)
5045
lock_scripts = {}
5146
type_scripts = {}
5247

5348
cell_outputs = ckb_transaction.cell_outputs.includes(:type_script).to_a
5449
cell_inputs = ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output)
5550

56-
(cell_inputs + cell_outputs).each do |cell|
51+
cell_inputs.each do |cell|
5752
lock_scripts[cell.lock_script.code_hash] = cell.lock_script.hash_type
5853
if cell.type_script
5954
type_scripts[cell.type_script.code_hash] = cell.type_script.hash_type
6055
end
6156
end
57+
cell_outputs.each do |cell|
58+
if cell.type_script
59+
type_scripts[cell.type_script.code_hash] = cell.type_script.hash_type
60+
end
61+
end
6262

6363
[lock_scripts, type_scripts]
6464
end
6565

66-
# 处理每个依赖
6766
def process_cell_dependencies(cell_deps, lock_scripts, type_scripts, out_points_attrs, contract_attrs, cell_deps_attrs, contract_roles)
6867
cell_deps.each do |cell_dep|
68+
is_used =
69+
case cell_dep.dep_type
70+
when "code"
71+
process_code_dep(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
72+
when "dep_group"
73+
process_dep_group(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
74+
end
75+
6976
cell_deps_attrs << {
7077
contract_analyzed: true,
78+
is_used:,
7179
ckb_transaction_id: cell_dep.ckb_transaction_id,
7280
contract_cell_id: cell_dep.contract_cell_id,
7381
dep_type: cell_dep.dep_type,
7482
}
75-
next if Contract.joins(:cell_deps_out_points).where(cell_deps_out_points: { contract_cell_id: cell_dep.contract_cell_id }).exists?
76-
77-
case cell_dep.dep_type
78-
when "code"
79-
process_code_dep(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
80-
when "dep_group"
81-
process_dep_group(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
82-
end
8383
end
8484
end
8585

86-
# 处理 "code" 类型依赖
8786
def process_code_dep(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
8887
cell_output = cell_dep.cell_output
8988
out_points_attrs << {
@@ -96,15 +95,18 @@ def process_code_dep(cell_dep, lock_scripts, type_scripts, out_points_attrs, con
9695
update_contract_roles(cell_output, lock_scripts, type_scripts, contract_roles)
9796

9897
if contract_roles[cell_output.id][:is_lock_script] || contract_roles[cell_output.id][:is_type_script]
99-
contract_attrs << build_contract_attr(cell_output, lock_scripts, type_scripts)
98+
contract_attrs << build_contract_attr(cell_output)
99+
true
100+
else
101+
false
100102
end
101103
end
102104

103-
# 处理 "dep_group" 类型依赖
104105
def process_dep_group(cell_dep, lock_scripts, type_scripts, out_points_attrs, contract_attrs, contract_roles)
105106
mid_cell = cell_dep.cell_output
106107
binary_data = mid_cell.binary_data
107108
out_points_count = binary_data[0, 4].unpack1("L<")
109+
is_used = false
108110

109111
0.upto(out_points_count - 1) do |i|
110112
part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<")
@@ -121,12 +123,13 @@ def process_dep_group(cell_dep, lock_scripts, type_scripts, out_points_attrs, co
121123
update_contract_roles(cell_output, lock_scripts, type_scripts, contract_roles)
122124

123125
if contract_roles[cell_output.id][:is_lock_script] || contract_roles[cell_output.id][:is_type_script]
124-
contract_attrs << build_contract_attr(cell_output, lock_scripts, type_scripts)
126+
contract_attrs << build_contract_attr(cell_output)
127+
is_used = is_used || true
125128
end
126129
end
130+
is_used
127131
end
128132

129-
# 更新 contract_roles
130133
def update_contract_roles(cell_output, lock_scripts, type_scripts, contract_roles)
131134
is_lock_script = (lock_scripts[cell_output.data_hash] || lock_scripts[cell_output.type_script&.script_hash]).present?
132135
is_type_script = (type_scripts[cell_output.data_hash] || type_scripts[cell_output.type_script&.script_hash]).present?
@@ -137,8 +140,7 @@ def update_contract_roles(cell_output, lock_scripts, type_scripts, contract_role
137140
contract_roles[cell_output.id][:hash_type] ||= data_type
138141
end
139142

140-
# 构建单个合约属性
141-
def build_contract_attr(cell_output, _lock_scripts, _type_scripts)
143+
def build_contract_attr(cell_output)
142144
{
143145
type_hash: cell_output.type_script&.script_hash,
144146
data_hash: cell_output.data_hash,
@@ -147,7 +149,6 @@ def build_contract_attr(cell_output, _lock_scripts, _type_scripts)
147149
}
148150
end
149151

150-
# 保存数据
151152
def save_cell_deps_out_points(attrs)
152153
CellDepsOutPoint.upsert_all(attrs.to_a, unique_by: %i[contract_cell_id deployed_cell_output_id]) if attrs.any?
153154
end
@@ -160,6 +161,6 @@ def save_contracts(attrs, roles)
160161
end
161162

162163
def save_cell_dependencies(attrs)
163-
CellDependency.upsert_all(attrs.to_a, unique_by: %i[ckb_transaction_id contract_cell_id dep_type], update_only: :contract_analyzed) if attrs.any?
164+
CellDependency.upsert_all(attrs.to_a, unique_by: %i[ckb_transaction_id contract_cell_id dep_type], update_only: %i[contract_analyzed is_used]) if attrs.any?
164165
end
165166
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class AddIsUsedToCellDependencies < ActiveRecord::Migration[7.0]
2+
def change
3+
remove_column :cell_dependencies, :contract_id, :bigint
4+
remove_column :cell_dependencies, :script_id, :bigint
5+
remove_column :cell_dependencies, :implicit, :boolean
6+
7+
add_column :cell_dependencies, :is_used, :boolean, default: true
8+
end
9+
end

db/structure.sql

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,15 +1044,13 @@ ALTER SEQUENCE public.cell_data_cell_output_id_seq OWNED BY public.cell_data.cel
10441044

10451045
CREATE TABLE public.cell_dependencies (
10461046
id bigint NOT NULL,
1047-
contract_id bigint,
10481047
ckb_transaction_id bigint NOT NULL,
10491048
dep_type integer,
10501049
contract_cell_id bigint NOT NULL,
1051-
script_id bigint,
1052-
implicit boolean DEFAULT true NOT NULL,
10531050
block_number bigint,
10541051
tx_index integer,
1055-
contract_analyzed boolean DEFAULT false
1052+
contract_analyzed boolean DEFAULT false,
1053+
is_used boolean DEFAULT true
10561054
);
10571055

10581056

@@ -4970,20 +4968,6 @@ CREATE INDEX index_cell_dependencies_on_block_number_and_tx_index ON public.cell
49704968
CREATE INDEX index_cell_dependencies_on_contract_analyzed ON public.cell_dependencies USING btree (contract_analyzed);
49714969

49724970

4973-
--
4974-
-- Name: index_cell_dependencies_on_contract_id; Type: INDEX; Schema: public; Owner: -
4975-
--
4976-
4977-
CREATE INDEX index_cell_dependencies_on_contract_id ON public.cell_dependencies USING btree (contract_id);
4978-
4979-
4980-
--
4981-
-- Name: index_cell_dependencies_on_script_id; Type: INDEX; Schema: public; Owner: -
4982-
--
4983-
4984-
CREATE INDEX index_cell_dependencies_on_script_id ON public.cell_dependencies USING btree (script_id);
4985-
4986-
49874971
--
49884972
-- Name: index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type; Type: INDEX; Schema: public; Owner: -
49894973
--
@@ -6379,6 +6363,7 @@ INSERT INTO "schema_migrations" (version) VALUES
63796363
('20241231022644'),
63806364
('20250103072945'),
63816365
('20250108053433'),
6382-
('20250126022459');
6366+
('20250126022459'),
6367+
('20250218062041');
63836368

63846369

0 commit comments

Comments
 (0)