Skip to content

Commit d22d39e

Browse files
authored
Merge pull request #2715 from nervosnetwork/testnet
Deploy to mainnet
2 parents 509155e + f3212ec commit d22d39e

File tree

6 files changed

+84
-73
lines changed

6 files changed

+84
-73
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ GEM
310310
net-protocol
311311
newrelic_rpm (8.12.0)
312312
nio4r (2.7.3)
313-
nokogiri (1.18.8)
313+
nokogiri (1.18.9)
314314
mini_portile2 (~> 2.8.2)
315315
racc (~> 1.4)
316316
pagy (5.10.1)

app/models/address.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Address < ApplicationRecord
1919

2020
validates :balance, :ckb_transactions_count, :interest, :dao_deposit,
2121
numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
22-
validates :lock_hash, presence: true, uniqueness: true
22+
validates :lock_hash, presence: true, uniqueness: true, on: :create
2323

2424
scope :visible, -> { where(visible: true) }
2525
scope :created_after, ->(block_timestamp) { where("block_timestamp >= ?", block_timestamp) }
@@ -99,7 +99,7 @@ def self.find_or_create_address(lock_script, block_timestamp, lock_script_id = n
9999
},
100100
)
101101
end
102-
address.save!
102+
address.save! if address.changed?
103103
address
104104
end
105105

app/models/ckb_sync/new_node_data_processor.rb

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class NewNodeDataProcessor
1010
value :reorg_started_at, global: true
1111
attr_accessor :local_tip_block, :pending_raw_block, :ckb_txs, :target_block, :target_block_number, :addrs_changes,
1212
:outputs, :inputs, :outputs_data, :udt_address_ids, :contained_address_ids,
13-
:contained_udt_ids, :cell_datas, :enable_cota, :token_transfer_ckb_tx_ids, :addr_tx_changes
13+
:contained_udt_ids, :cell_datas, :enable_cota, :token_transfer_ckb_tx_ids, :addr_tx_changes, :redis_keys, :tx_previous_outputs
1414

1515
def initialize(enable_cota = ENV["COTA_AGGREGATOR_URL"].present?)
1616
@enable_cota = enable_cota
@@ -28,6 +28,7 @@ def call
2828
return if target_block_number > tip_block_number - @offset.to_i
2929

3030
target_block = CkbSync::Api.instance.get_block_by_number(target_block_number)
31+
3132
if forked?(target_block, local_tip_block)
3233
self.reorg_started_at = Time.now
3334
res = RevertBlockJob.perform_now(local_tip_block)
@@ -45,11 +46,14 @@ def call
4546
rescue StandardError => e
4647
Rails.logger.error e.message
4748
puts e.backtrace.join("\n")
49+
Rails.cache.delete_multi(@redis_keys)
4850
raise e
4951
end
5052

5153
def process_block(node_block, refresh_balance: true)
5254
local_block = nil
55+
@redis_keys = []
56+
@tx_previous_outputs = {}
5357

5458
ApplicationRecord.transaction do
5559
# build node data
@@ -414,11 +418,10 @@ def update_or_create_udt_accounts!(local_block)
414418
next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token
415419
spore_cell did_cell omiga_inscription xudt xudt_compatible))
416420

417-
address = Address.find(udt_output.address_id)
418421
udt_type = udt_type(udt_output.cell_type)
419-
udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type:).select(:id,
422+
udt_account = UdtAccount.where(address_id: udt_output.address_id).where(type_hash: udt_output.type_hash, udt_type:).select(:id,
420423
:created_at).first
421-
amount = udt_account_amount(udt_type, udt_output.type_hash, address)
424+
amount = udt_account_amount(udt_type, udt_output.type_hash, udt_output.address_id)
422425
nft_token_id =
423426
case udt_type
424427
when "nrc_721_token"
@@ -440,16 +443,15 @@ def update_or_create_udt_accounts!(local_block)
440443
end
441444

442445
local_block.ckb_transactions.pluck(:id).each do |tx_id| # iterator over each tx id for better sql performance
443-
CellOutput.where(consumed_by_id: tx_id).select(:id, :address_id,
444-
:type_hash, :cell_type).each do |udt_output|
446+
cell_outputs = @tx_previous_outputs[tx_id] || []
447+
cell_outputs.each do |udt_output|
445448
next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token
446449
spore_cell did_cell omiga_inscription xudt xudt_compatible))
447450

448-
address = Address.find(udt_output.address_id)
449451
udt_type = udt_type(udt_output.cell_type)
450-
udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type:).select(:id,
452+
udt_account = UdtAccount.where(address_id: udt_output.address_id).where(type_hash: udt_output.type_hash, udt_type:).select(:id,
451453
:created_at).first
452-
amount = udt_account_amount(udt_type, udt_output.type_hash, address)
454+
amount = udt_account_amount(udt_type, udt_output.type_hash, udt_output.address_id)
453455
udt = Udt.where(type_hash: udt_output.type_hash, udt_type:).select(:id, :udt_type, :full_name,
454456
:symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take!
455457
if udt_account.present?
@@ -458,7 +460,7 @@ def update_or_create_udt_accounts!(local_block)
458460
udt_accounts_attributes << { id: udt_account.id, amount:,
459461
created_at: udt.created_at }
460462
when "m_nft_token", "nrc_721_token", "spore_cell", "did_cell"
461-
udt_account.destroy unless address.cell_outputs.live.where(cell_type: udt_type).where(type_hash: udt_output.type_hash).exists?
463+
udt_account.destroy unless CellOutput.live.where(address_id: udt_output.address_id).where(cell_type: udt_type).where(type_hash: udt_output.type_hash).exists?
462464
end
463465
end
464466
end
@@ -487,12 +489,12 @@ def udt_type(cell_type)
487489
cell_type == "udt" ? "sudt" : cell_type
488490
end
489491

490-
def udt_account_amount(udt_type, type_hash, address)
492+
def udt_account_amount(udt_type, type_hash, address_id)
491493
case udt_type
492494
when "sudt", "ssri"
493-
address.cell_outputs.live.udt.where(type_hash:).sum(:udt_amount)
495+
CellOutput.live.where(address_id:).udt.where(type_hash:).sum(:udt_amount)
494496
when "xudt", "xudt_compatible", "omiga_inscription", "m_nft_token", "spore_cell", "did_cell"
495-
address.cell_outputs.live.where(cell_type: udt_type).where(type_hash:).sum(:udt_amount)
497+
CellOutput.live.where(address_id:).where(cell_type: udt_type).where(type_hash:).sum(:udt_amount)
496498
else
497499
0
498500
end
@@ -558,7 +560,7 @@ def update_block_info!(local_block)
558560
total_transaction_fee: local_block.ckb_transactions.sum(:transaction_fee),
559561
ckb_transactions_count: local_block.ckb_transactions.count,
560562
live_cell_changes: local_block.ckb_transactions.sum(&:live_cell_changes),
561-
address_ids: local_block.ckb_transactions.map(&:contained_address_ids).flatten.uniq,
563+
address_ids: @contained_address_ids.map(&:to_a).flatten.uniq
562564
)
563565
end
564566

@@ -584,7 +586,7 @@ def build_udts!(local_block, outputs, outputs_data)
584586
attrs[:pre_udt_hash] = pre_closed_info.udt_hash
585587
attrs[:is_repeated_symbol] = pre_closed_info.is_repeated_symbol
586588
else
587-
attrs[:is_repeated_symbol] = OmigaInscriptionInfo.where(symbol: info[:symbol].strip).exists?
589+
attrs[:is_repeated_symbol] = OmigaInscriptionInfo.where(symbol: CkbUtils.sanitize_string(info[:symbol])).exists?
588590
end
589591
OmigaInscriptionInfo.upsert(attrs, unique_by: :udt_hash)
590592
[info[:udt_hash], "omiga_inscription"]
@@ -598,8 +600,8 @@ def build_udts!(local_block, outputs, outputs_data)
598600
end
599601

600602
unless Udt.where(type_hash:).exists?
601-
nft_token_attr = { full_name: nil, icon_file: nil,
602-
published: false, symbol: nil, decimal: nil, nrc_factory_cell_id: nil }
603+
nft_token_attr = { full_name: "", icon_file: "",
604+
published: false, symbol: "", decimal: nil, nrc_factory_cell_id: nil }
603605
issuer_address = CkbUtils.generate_address(output.lock, CKB::Address::Version::CKB2021)
604606
case cell_type
605607
when "m_nft_token"
@@ -610,15 +612,15 @@ def build_udts!(local_block, outputs, outputs_data)
610612
parsed_class_data = CkbUtils.parse_token_class_data(m_nft_class_cell.data)
611613
TokenCollection.find_or_create_by(
612614
standard: "m_nft",
613-
name: parsed_class_data.name,
615+
name: CkbUtils.sanitize_string(parsed_class_data.name),
614616
cell_id: m_nft_class_cell.id,
615617
block_timestamp: m_nft_class_cell.block_timestamp,
616-
icon_url: parsed_class_data.renderer,
618+
icon_url: CkbUtils.sanitize_string(parsed_class_data.renderer),
617619
creator_id: m_nft_class_cell.address_id,
618620
)
619621

620-
nft_token_attr[:full_name] = parsed_class_data.name
621-
nft_token_attr[:icon_file] = parsed_class_data.renderer
622+
nft_token_attr[:full_name] = CkbUtils.sanitize_string(parsed_class_data.name)
623+
nft_token_attr[:icon_file] = CkbUtils.sanitize_string(parsed_class_data.renderer)
622624
nft_token_attr[:published] = true
623625
end
624626
when "spore_cell", "did_cell"
@@ -630,7 +632,7 @@ def build_udts!(local_block, outputs, outputs_data)
630632
if spore_cluster_type_ids.present?
631633
spore_cluster_cell = CellOutput.where(type_script_id: spore_cluster_type_ids, status: %i[pending live]).last
632634
parsed_cluster_data = CkbUtils.parse_spore_cluster_data(spore_cluster_cell.data)
633-
nft_token_attr[:full_name] = parsed_cluster_data[:name]
635+
nft_token_attr[:full_name] = CkbUtils.sanitize_string(parsed_cluster_data[:name].to_s)
634636
end
635637
end
636638
when "nrc_721_token"
@@ -648,8 +650,8 @@ def build_udts!(local_block, outputs, outputs_data)
648650
nft_token_attr[:published] = true
649651
when "omiga_inscription_info"
650652
info = CkbUtils.parse_omiga_inscription_info(outputs_data[tx_index][index])
651-
nft_token_attr[:full_name] = info[:name]
652-
nft_token_attr[:symbol] = info[:symbol]
653+
nft_token_attr[:full_name] = CkbUtils.sanitize_string(info[:name])
654+
nft_token_attr[:symbol] = CkbUtils.sanitize_string(info[:symbol])
653655
nft_token_attr[:decimal] = info[:decimal]
654656
nft_token_attr[:published] = true
655657
when "xudt", "xudt_compatible"
@@ -659,8 +661,8 @@ def build_udts!(local_block, outputs, outputs_data)
659661
items.each_with_index do |output, index|
660662
if output.type&.code_hash == CkbSync::Api.instance.unique_cell_code_hash
661663
info = CkbUtils.parse_unique_cell(outputs_data[tx_index][index])
662-
nft_token_attr[:full_name] = info[:name]
663-
nft_token_attr[:symbol] = info[:symbol]
664+
nft_token_attr[:full_name] = CkbUtils.sanitize_string(info[:name])
665+
nft_token_attr[:symbol] = CkbUtils.sanitize_string(info[:symbol])
664666
nft_token_attr[:decimal] = info[:decimal]
665667
nft_token_attr[:published] = true
666668
end
@@ -724,7 +726,7 @@ def update_ckb_txs_rel_and_fee(
724726
0
725727
else
726728
CkbUtils.ckb_transaction_fee(tx, input_capacities[tx_index],
727-
output_capacities[tx_index])
729+
output_capacities[tx_index], @tx_previous_outputs[tx_id] || [])
728730
end,
729731
created_at: tx["created_at"],
730732
updated_at: Time.current,
@@ -876,9 +878,11 @@ def build_addresses!(outputs, local_block)
876878
script_hash = item.lock.compute_hash
877879
key = "lock_script_hash_#{script_hash}"
878880
lock_script_id = Rails.cache.read(key) || LockScript.find_by(script_hash: script_hash)&.id
879-
unless Rails.cache.exist?("address_lock_hash_#{script_hash}")
881+
address_redis_key = "address_lock_hash_#{script_hash}"
882+
unless Rails.cache.exist?(address_redis_key)
880883
address = Address.find_or_create_address(item.lock, local_block.timestamp, lock_script_id)
881-
Rails.cache.write("address_lock_hash_#{script_hash}", address.id)
884+
Rails.cache.write(address_redis_key, address.id)
885+
@redis_keys << address_redis_key
882886
end
883887
end
884888
end
@@ -895,6 +899,7 @@ def build_scripts(outputs)
895899
unless Rails.cache.exist?(key)
896900
if lock_script = LockScript.find_by(script_hash: script_hash)
897901
Rails.cache.write(key, lock_script.id)
902+
@redis_keys << key
898903
else
899904
locks_attributes << script_attributes(output.lock, script_hash)
900905
end
@@ -906,6 +911,7 @@ def build_scripts(outputs)
906911
unless Rails.cache.exist?(key)
907912
if type_script = TypeScript.find_by(script_hash: script_hash)
908913
Rails.cache.write(key, type_script.id)
914+
@redis_keys << key
909915
else
910916
types_attributes << script_attributes(output.type, script_hash)
911917
end
@@ -1028,10 +1034,18 @@ def build_cell_outputs!(
10281034
end
10291035
items.each do |item|
10301036
lock_script_hash = item.lock.compute_hash
1031-
address_id = Rails.cache.read("address_lock_hash_#{lock_script_hash}")
1037+
address_key = "address_lock_hash_#{lock_script_hash}"
1038+
address_id = Rails.cache.read(address_key)
10321039
unless address_id
10331040
address_id = Address.find_by(lock_hash: lock_script_hash)&.id
1034-
Rails.cache.write("address_lock_hash_#{lock_script_hash}", address_id) if address_id
1041+
unless address_id
1042+
lock_script_id = Rails.cache.read("lock_script_hash_#{lock_script_hash}") || LockScript.find_by(script_hash: lock_script_hash)&.id
1043+
address_id = Address.find_or_create_address(item.lock, local_block.timestamp, lock_script_id).id
1044+
end
1045+
if address
1046+
Rails.cache.write(address_key, address_id)
1047+
@redis_keys << key
1048+
end
10351049
end
10361050
cell_data = node_block.transactions[tx_index].outputs_data[cell_index]
10371051
change_rec = addrs_changes[address_id]
@@ -1190,9 +1204,12 @@ def cell_input_attributes(input, ckb_transaction_id, local_block_id,
11901204
}
11911205
else
11921206
# previous_output = prev_outputs["#{input.previous_output.tx_hash}-#{input.previous_output.index}"]
1193-
previous_output = CellOutput.find_by tx_hash: input.previous_output.tx_hash,
1207+
previous_output = CellOutput.live.find_by tx_hash: input.previous_output.tx_hash,
11941208
cell_index: input.previous_output.index
11951209

1210+
@tx_previous_outputs[ckb_transaction_id] = [] if @tx_previous_outputs[ckb_transaction_id] == nil
1211+
@tx_previous_outputs[ckb_transaction_id] << previous_output
1212+
11961213
{
11971214
cell_input: {
11981215
ckb_transaction_id:,
@@ -1214,7 +1231,7 @@ def cell_input_attributes(input, ckb_transaction_id, local_block_id,
12141231
cell_index: input.previous_output.index,
12151232
status: "dead",
12161233
consumed_by_id: ckb_transaction_id,
1217-
consumed_block_timestamp: CkbTransaction.find(ckb_transaction_id).block_timestamp,
1234+
consumed_block_timestamp: @local_block.timestamp,
12181235
},
12191236
capacity: previous_output.capacity,
12201237
type_hash: previous_output.type_hash,
@@ -1248,10 +1265,10 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da
12481265
# First update status thus we can use upsert later. otherwise, we may not be able to
12491266
# locate correct record according to tx_hash
12501267
binary_hashes = CkbUtils.hexes_to_bins_sql(hashes)
1251-
pending_txs = CkbTransaction.where("tx_hash IN (#{binary_hashes})").where(tx_status: :pending).pluck(
1268+
pending_txs = CkbTransaction.where(tx_status: :pending).where("tx_hash IN (#{binary_hashes})").pluck(
12521269
:tx_hash, :confirmation_time
12531270
)
1254-
CkbTransaction.where("tx_hash IN (#{binary_hashes}) AND tx_status = 0").update_all tx_status: "committed"
1271+
CkbTransaction.where(tx_status: :pending).where("tx_hash IN (#{binary_hashes})").update_all tx_status: "committed" if pending_txs.size > 0
12551272
txs = []
12561273
ckb_transactions_attributes.each_slice(500) do |batch|
12571274
txs.concat CkbTransaction.upsert_all(batch, unique_by: %i[tx_status tx_hash],
@@ -1477,10 +1494,12 @@ def generate_address_in_advance(cellbase, block_timestamp)
14771494
script_hash: script_hash
14781495
).id
14791496
Rails.cache.write(key, lock_script_id)
1497+
@redis_keys << key
14801498
end
14811499
unless Rails.cache.exist?("address_lock_hash_#{script_hash}")
14821500
address = Address.find_or_create_address(lock_script, block_timestamp, lock_script_id)
14831501
Rails.cache.write("address_lock_hash_#{script_hash}", address.id)
1502+
@redis_keys << "address_lock_hash_#{script_hash}"
14841503
end
14851504
end
14861505

@@ -1502,10 +1521,10 @@ def update_nrc_factory_cell_info(type_script, output_data)
15021521
)
15031522
parsed_factory_data = CkbUtils.parse_nrc_721_factory_data(output_data)
15041523
factory_cell.update(
1505-
name: parsed_factory_data.name,
1506-
symbol: parsed_factory_data.symbol,
1507-
base_token_uri: parsed_factory_data.base_token_uri,
1508-
extra_data: parsed_factory_data.extra_data,
1524+
name: CkbUtils.sanitize_string(parsed_factory_data.name),
1525+
symbol: CkbUtils.sanitize_string(parsed_factory_data.symbol),
1526+
base_token_uri: CkbUtils.sanitize_string(parsed_factory_data.base_token_uri),
1527+
extra_data: CkbUtils.sanitize_string(parsed_factory_data.extra_data),
15091528
)
15101529
end
15111530

app/models/statistic_info.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ def self.hash_rate(block_number)
9090
end
9191

9292
define_logic :address_balance_ranking do
93+
ActiveRecord::Base.connection.execute("SET statement_timeout = 0")
9394
addresses = Address.visible.where("balance > 0").order(balance: :desc).limit(50)
95+
ActiveRecord::Base.connection.execute("RESET statement_timeout")
9496
addresses.each.with_index(1).map do |address, index|
9597
{ address: address.address_hash, balance: address.balance.to_s,
9698
ranking: index.to_s }
@@ -107,10 +109,13 @@ def self.hash_rate(block_number)
107109
end
108110

109111
define_logic :transaction_fee_rates do
112+
ActiveRecord::Base.connection.execute("SET statement_timeout = 0")
110113
txs = CkbTransaction.tx_committed.
111114
where("bytes > 0 and transaction_fee > 0 and confirmation_time > 0").
112115
order("id desc").limit(10000).
113116
pluck(:id, :created_at, :transaction_fee, :bytes, :confirmation_time)
117+
ActiveRecord::Base.connection.execute("RESET statement_timeout")
118+
114119
txs.map do |id, created_at, transaction_fee, bytes, confirmation_time|
115120
{
116121
id:,

0 commit comments

Comments
 (0)