Skip to content

Commit 509155e

Browse files
authored
Merge pull request #2695 from nervosnetwork/testnet
Deploy to mainnet
2 parents 23832b6 + fa0d29b commit 509155e

File tree

13 files changed

+324
-436
lines changed

13 files changed

+324
-436
lines changed

app/interactions/addresses/live_cells.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def filter_by_tag(scope)
6363
scope.where(lock_script_id: filtered_ids)
6464
when "deployment"
6565
scope_ids = scope.pluck(:id)
66-
matched_ids = Contract.where(deployed_cell_output_id: scope_ids).pluck(:deployed_cell_output_id)
66+
deployed_ids = Contract.pluck(:deployed_cell_output_id)
67+
matched_ids = scope_ids & deployed_ids
6768
scope.where(id: matched_ids)
6869
else
6970
CellOutput.none

app/jobs/revert_block_job.rb

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ def perform(local_tip_block = nil)
2222
end
2323
benchmark :recalculate_udt_transactions_count, local_tip_block
2424
benchmark :decrease_records_count, local_tip_block
25+
benchmark :update_address_balance_and_ckb_transactions_count, local_tip_block
2526

2627
ApplicationRecord.benchmark "invalid! block" do
2728
local_tip_block.invalid!
2829
end
2930

3031
benchmark :recalculate_udt_accounts, udt_type_hashes, local_tip_block
31-
benchmark :update_address_balance_and_ckb_transactions_count, local_tip_block
3232
benchmark :revert_block_rewards, local_tip_block
3333
ForkedEvent.create!(block_number: local_tip_block.number, epoch_number: local_tip_block.epoch,
3434
block_timestamp: local_tip_block.timestamp)
@@ -40,22 +40,76 @@ def perform(local_tip_block = nil)
4040
end
4141

4242
def update_address_balance_and_ckb_transactions_count(local_tip_block)
43-
snapshots = AddressBlockSnapshot.where.not(block_id: local_tip_block.id).where(address_id: local_tip_block.address_ids).order(block_number: :desc).distinct.group_by(&:address_id)
44-
local_tip_block.contained_addresses.each do |address|
45-
snapshot = snapshots.fetch(address.id, []).first
46-
if snapshot.present?
47-
attrs = snapshot.final_state
48-
address.update!(attrs)
49-
else
50-
address.live_cells_count = address.cell_outputs.live.count
51-
address.ckb_transactions_count = AccountBook.tx_committed.where(address_id: address.id).count
52-
address.dao_transactions_count = DaoEvent.processed.where(address_id: address.id).distinct.count(:ckb_transaction_id)
53-
address.cal_balance!
54-
address.save!
55-
end
43+
select_fields = [
44+
"address_id",
45+
"COUNT(*) AS cells_count",
46+
"SUM(capacity) AS total_capacity",
47+
"SUM(CASE WHEN type_hash IS NOT NULL OR data_hash IS NOT NULL THEN capacity ELSE 0 END) AS balance_occupied",
48+
]
49+
output_addrs =
50+
local_tip_block.cell_outputs.live.select(select_fields.join(", ")).group(:address_id)
51+
input_addrs =
52+
CellOutput.where(consumed_block_timestamp: local_tip_block.timestamp).select(select_fields.join(", ")).group(:address_id)
53+
out_hash = output_addrs.each_with_object({}) do |row, h|
54+
h[row.address_id] = {
55+
cells_count: row.cells_count.to_i,
56+
total_capacity: row.total_capacity.to_i,
57+
balance_occupied: row.balance_occupied.to_i,
58+
}
59+
end
60+
61+
in_hash = input_addrs.each_with_object({}) do |row, h|
62+
h[row.address_id] = {
63+
cells_count: row.cells_count.to_i,
64+
total_capacity: row.total_capacity.to_i,
65+
balance_occupied: row.balance_occupied.to_i,
66+
}
5667
end
5768

58-
AddressBlockSnapshot.where(block_id: local_tip_block.id).delete_all
69+
# Merge keys
70+
all_ids = in_hash.keys | out_hash.keys
71+
72+
# 计算差值
73+
address_balance_diff = all_ids.each_with_object({}) do |addr_id, h|
74+
input = in_hash[addr_id] || { cells_count: 0, total_capacity: 0, balance_occupied: 0 }
75+
output = out_hash[addr_id] || { cells_count: 0, total_capacity: 0, balance_occupied: 0 }
76+
77+
h[addr_id] = {
78+
cells_count: input[:cells_count] - output[:cells_count],
79+
total_capacity: input[:total_capacity] - output[:total_capacity],
80+
balance_occupied: input[:balance_occupied] - output[:balance_occupied],
81+
}
82+
end
83+
# Preload dao transaction counts for all addresses in one query
84+
dao_tx_counts = DaoEvent.processed.
85+
where(block_id: local_tip_block.id, address_id: all_ids).
86+
group(:address_id).
87+
distinct.
88+
count(:ckb_transaction_id)
89+
tx_count_diffs = AccountBook.tx_committed.
90+
where(block_number: local_tip_block.number, address_id: all_ids).
91+
group(:address_id).
92+
count
93+
94+
changes =
95+
address_balance_diff.map do |address_id, changes|
96+
tx_count_diff = tx_count_diffs[address_id] || 0
97+
dao_tx_count_diff = dao_tx_counts[address_id] || 0
98+
{ address_id: address_id }.merge(changes).merge({ ckb_transactions_count: tx_count_diff, dao_transactions_count: dao_tx_count_diff })
99+
end
100+
101+
changes.each do |change|
102+
addr = Address.find_by_id(change[:address_id])
103+
if addr
104+
addr.update!(
105+
live_cells_count: addr.live_cells_count + change[:cells_count],
106+
ckb_transactions_count: addr.ckb_transactions_count - change[:ckb_transactions_count],
107+
balance: addr.balance + change[:total_capacity],
108+
balance_occupied: addr.balance_occupied + change[:balance_occupied],
109+
dao_transactions_count: addr.dao_transactions_count - change[:dao_transactions_count]
110+
)
111+
end
112+
end
59113
end
60114

61115
def recalculate_udt_transactions_count(local_tip_block)

app/models/address.rb

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,20 @@ def self.find_by_address_hash(address_hash, *_args, **_kargs)
5151
def self.find_or_create_by_address_hash(address_hash, block_timestamp = 0)
5252
parsed = CkbUtils.parse_address(address_hash)
5353
lock_hash = parsed.script.compute_hash
54-
lock_script = LockScript.find_by(
55-
code_hash: parsed.code_hash,
56-
hash_type: parsed.hash_type,
57-
args: parsed.args,
58-
)
5954

60-
create_with(
61-
address_hash: CkbUtils.generate_address(parsed.script),
62-
block_timestamp:,
63-
lock_script_id: lock_script&.id,
64-
).find_or_create_by lock_hash:
65-
end
66-
67-
def self.find_or_create_by_lock(lock_script)
68-
lock_hash = lock_script.compute_hash
69-
address_hash = CkbUtils.generate_address(lock_script)
70-
address = Address.find_or_initialize_by(lock_hash:)
71-
# force use new version address
72-
address.address_hash = address_hash
73-
address.lock_script = LockScript
74-
address.save!
75-
address
55+
key = "lock_script_hash_#{lock_hash}"
56+
lock_script_id = Rails.cache.read(key) || LockScript.find_by(script_hash: lock_hash)&.id
57+
58+
address_id = Rails.cache.read("address_lock_hash_#{lock_hash}")
59+
if address_id
60+
return address_id
61+
else
62+
create_with(
63+
address_hash: CkbUtils.generate_address(parsed.script),
64+
block_timestamp:,
65+
lock_script_id: lock_script_id,
66+
).find_or_create_by(lock_hash:)&.id
67+
end
7668
end
7769

7870
# @param lock_script [CKB::Types::Script]

app/models/cell_output.rb

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ class CellOutput < ApplicationRecord
7979

8080
attribute :tx_hash, :ckb_hash
8181

82-
attr_accessor :raw_address
83-
8482
scope :consumed_after, ->(block_timestamp) {
8583
where("consumed_block_timestamp >= ?", block_timestamp)
8684
}
@@ -110,8 +108,6 @@ class CellOutput < ApplicationRecord
110108
scope :by_scripts, ->(lock_script_ids, type_script_ids) { where("lock_script_id IN (?) OR type_script_id IN (?)", lock_script_ids, type_script_ids) }
111109
scope :established_status, -> { where(status: ["live", "dead"]) }
112110

113-
before_create :setup_address
114-
115111
def data=(new_data)
116112
@data = new_data
117113
if new_data
@@ -134,13 +130,6 @@ def binary_data
134130
cell_datum&.data
135131
end
136132

137-
def setup_address
138-
if raw_address
139-
self.address = Address.find_or_create_by_address_hash(raw_address,
140-
block_timestamp)
141-
end
142-
end
143-
144133
# @return [Boolean]
145134
def occupied?
146135
!free?

0 commit comments

Comments
 (0)