Skip to content

Commit ae84350

Browse files
authored
Merge pull request #2464 from nervosnetwork/testnet
Deploy to mainnet
2 parents c540597 + e4d5de5 commit ae84350

File tree

7 files changed

+102
-22
lines changed

7 files changed

+102
-22
lines changed

app/models/account_book.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ class AccountBook < ApplicationRecord
1111
# id :bigint not null, primary key
1212
# address_id :bigint
1313
# ckb_transaction_id :bigint
14+
# income :decimal(30, )
15+
# block_number :bigint
16+
# tx_index :integer
1417
#
1518
# Indexes
1619
#
1720
# index_account_books_on_address_id_and_ckb_transaction_id (address_id,ckb_transaction_id) UNIQUE
21+
# index_account_books_on_block_number_and_tx_index (block_number,tx_index)
1822
# index_account_books_on_ckb_transaction_id (ckb_transaction_id)
1923
#

app/models/ckb_sync/new_node_data_processor.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class NewNodeDataProcessor
88
include Redis::Objects
99

1010
value :reorg_started_at, global: true
11-
attr_accessor :local_tip_block, :pending_raw_block, :ckb_txs, :target_block, :addrs_changes,
11+
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,
1313
:contained_udt_ids, :cell_datas, :enable_cota, :token_transfer_ckb_tx_ids
1414

@@ -23,7 +23,7 @@ def initialize(enable_cota = ENV["COTA_AGGREGATOR_URL"].present?)
2323
def call
2424
@local_tip_block = Block.recent.first
2525
tip_block_number = @tip_block_number = CkbSync::Api.instance.get_tip_block_number
26-
target_block_number = local_tip_block.present? ? local_tip_block.number + 1 : 0
26+
@target_block_number = local_tip_block.present? ? local_tip_block.number + 1 : 0
2727
puts "Offset #{@offset}" if @offset > 0
2828
return if target_block_number > tip_block_number - @offset.to_i
2929

@@ -71,7 +71,7 @@ def process_block(node_block, refresh_balance: true)
7171

7272
benchmark :process_ckb_txs, node_block, ckb_txs, contained_address_ids,
7373
contained_udt_ids, tags, udt_address_ids
74-
addrs_changes = Hash.new { |hash, key| hash[key] = {} }
74+
@addrs_changes = Hash.new { |hash, key| hash[key] = {} }
7575

7676
input_capacities, output_capacities = benchmark :build_cells_and_locks!, local_block, node_block, ckb_txs, inputs, outputs,
7777
tags, udt_address_ids, contained_udt_ids, contained_address_ids, addrs_changes, token_transfer_ckb_tx_ids, cell_deps
@@ -678,8 +678,8 @@ def update_ckb_txs_rel_and_fee(
678678
ckb_txs.each do |tx|
679679
tx_id = tx["id"]
680680
full_tx_address_ids +=
681-
contained_addr_ids[tx_index].to_a.map do |a|
682-
{ address_id: a, ckb_transaction_id: tx_id }
681+
contained_addr_ids[tx_index].to_a.map do |address_id|
682+
{ address_id:, ckb_transaction_id: tx_id, income: addrs_changes[address_id][:balance_diff], block_number: target_block_number, tx_index: }
683683
end
684684
full_tx_udt_ids += contained_udt_ids[tx_index].to_a.map do |u|
685685
{ udt_id: u, ckb_transaction_id: tx_id }

app/models/ckb_sync/transaction_parser.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module CkbSync
22
class TransactionParser
33
attr_reader :transaction, :extra_data
44
attr_accessor :tx_attr, :cell_outputs_attrs, :cell_data_attrs, :cell_inputs_attrs, :cell_deps_attrs, :witnesses_attrs, :header_deps_attrs, :lock_script_attrs, :addresses_attrs,
5-
:account_books_attrs, :type_script_attrs
5+
:output_account_books_attrs, :type_script_attrs
66

77
# {"transaction"=>{"version"=>"0x0", "cell_deps"=>[{"out_point"=>{"tx_hash"=>"0xcd52d714ddea04d2917892f16d47cbd0bbbb7d9ba281233ec4021f79fc34bccc", "index"=>"0x0"}, "dep_type"=>"code"}, {"out_point"=>{"tx_hash"=>"0x9154df4f7336402114d04495175b37390ce86a4906d2d4001cf02c3e6d97f39c", "index"=>"0x0"}, "dep_type"=>"code"}, {"out_point"=>{"tx_hash"=>"0xbcd73881ba53f1cd95d0c855395c4ffe6f54e041765d9ab7602d48a7cb71612e", "index"=>"0x0"}, "dep_type"=>"code"}, {"out_point"=>{"tx_hash"=>"0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37", "index"=>"0x0"}, "dep_type"=>"dep_group"}, {"out_point"=>{"tx_hash"=>"0x053fdb4ed3181eab3a3a5f05693b53a8cdec0a24569e16369f444bac48be7de9", "index"=>"0x0"}, "dep_type"=>"code"}], "header_deps"=>[], "inputs"=>[{"since"=>"0x40000000669f4e30", "previous_output"=>{"tx_hash"=>"0x3d9a919a18d2cc2b64d2063626c75a6c97e87d2e8c30ec7bd33ef3ce14039934", "index"=>"0x0"}}, {"since"=>"0x0", "previous_output"=>{"tx_hash"=>"0x3d9a919a18d2cc2b64d2063626c75a6c97e87d2e8c30ec7bd33ef3ce14039934", "index"=>"0x1"}}, {"since"=>"0x0", "previous_output"=>{"tx_hash"=>"0x3d9a919a18d2cc2b64d2063626c75a6c97e87d2e8c30ec7bd33ef3ce14039934", "index"=>"0x2"}}], "outputs"=>[{"capacity"=>"0x7676d7e00", "lock"=>{"code_hash"=>"0x79f90bb5e892d80dd213439eeab551120eb417678824f282b4ffb5f21bad2e1e", "hash_type"=>"type", "args"=>"0x00c267a8b93cdae15fb06325f11a72b1047bd4d33c00"}, "type"=>{"code_hash"=>"0x1e44736436b406f8e48a30dfbddcf044feb0c9eebfe63b0f81cb5bb727d84854", "hash_type"=>"type", "args"=>"0x86c7429247beba7ddd6e4361bcdfc0510b0b644131e2afb7e486375249a01802"}}, {"capacity"=>"0x3691d6afc000", "lock"=>{"code_hash"=>"0x7f5a09b8bd0e85bcf2ccad96411ccba2f289748a1c16900b0635c2ed9126f288", "hash_type"=>"type", "args"=>"0x702359ea7f073558921eb50d8c1c77e92f760c8f8656bde4995f26b8963e2dd8f245705db4fe72be953e4f9ee3808a1700a578341aa80a8b2349c236c4af64e5e077710000000000"}, "type"=>nil}, {"capacity"=>"0xe529edc1ba", "lock"=>{"code_hash"=>"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", "hash_type"=>"type", "args"=>"0xc267a8b93cdae15fb06325f11a72b1047bd4d33c"}, "type"=>nil}], "outputs_data"=>["0xa0cf6037bfc238b179b74a30a9b12e15a4fbdd8881aebc8e5a66a8b5b5c95f0a6d833f7d5c1f8130fa2688970b421a57fbdffeff55bae5b4676043c543355799abe60200de0991241ff42c0255e2e2f65d114951c0a144e89d35527c582adc6603ff1ea2e17771000000000000000000000000000000000000000000000000000000000000000000000000001f779faa1f6184b10c9d865f62bba000e5d54e00a5d4b98cd768e43e376f68421a6b49de900100007c777100000000000001", "0x", "0x"], "witnesses"=>["0xc1030000100000006900000069000000550000005500000010000000550000005500000041000000e74f7818a6d2d1dda76593b30973967cd15fc6853731ecc0a5cf42cdb81859005b4a22781fa67973ccfbd3c5d0c1ccdd62506e2e99a049c19adc972e3909511a0054030000000000005003000010000000480300004c030000380300001c0000006c01000070010000740100007801000034030000500100002c000000340000005400000074000000940000009c000000c0000000e4000000e80000000c010000e0777100000000001c0000000200000014000000715ab282b873b79a7be8b0e8c13c4e8966a52040f7cfb9cf096dc32d69cac2b6f884bb2b1a8bb01660f3edc613ccfbeb7f3506d6f245705db4fe72be953e4f9ee3808a1700a578341aa80a8b2349c236c4af64e51a6b49de900100006d833f7d5c1f8130fa2688970b421a57fbdffeff55bae5b4676043c543355799abe602006d833f7d5c1f8130fa2688970b421a57fbdffeff55bae5b4676043c543355799abe602000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024ea893c4fa601a048b1d3a8de265fd8b442ba2a1ac37d85dfe320a7c8c2069a000000000000000004000000b80100004c4f05500d310a045d500ed295c313abef5ae2862c24393fdacc2e2e4c2ba76b43828b9d505cfc4cbb06c1083817aa14c6e06df9c300687a61fa0ec947fe79962fb9c557845058409c8c929c05fe19cc818cd0da6f0bf887cdb7ca4e465e85f7796ddd0e1528507119e4869f5a24e613de92605fb220451c0d1727d65f1c030815155c3cb7acd350a011fc6c115f153c24055880abd2a1253281e4e8a894e2a0546ea8799b057667507cee0dc2c4b8b171a0331b3f9ec02cf8906ef52a873523d2dbe3ff9e5f58699a4f01509d5c06f8f45bfaf59625237cb06c099a9c2a59752d5c1032e503ef39fbded2d7506989c3d61168d80ae0e27a2b2ca904f768cc698f783fd4f5d6c45c1b7dd66bbb5090d5dd9cd0b9f66197a69ea30e933982c98b99a067b37a8d0b7adc687d8c8db44f0150da2c4d3f8cc63b7b827c24c55098ec49cc88a9c81ff07abb0057f7d1dc05c9304f0350287fc2f5b5005ff558ae296f4e9cb354876829fa9562d215fbf7cd9536d5e0e550a03eb9492d55fc2d9d63faf8ea6121d66a86230f0752178ab5643a81abff8380508ad8ce2ac94cf885730b362ca4b81787bf85b48d7f72ef7816130bdc54433f644fe9040000000000000000000000", "0x10000000100000001000000010000000", "0x55000000100000005500000055000000410000001ccd614d2dbafb3384f6da8d50fc6cef21e0280c05397a93072d1560c81fd8bf347d299d7879e7b7682812fbb9fd5841c97c2f92b5c3e64737aa61c9fab7a01401"], "hash"=>"0x74758da9a59938724839e442d6e2b10b5c69e8fa398d4bd4d9b64fd311801ac1"}, "cycles"=>"0x4819ea", "size"=>"0x853", "fee"=>"0x853", "timestamp"=>"0x190de4b95b3"}
88
def initialize(tx, extra_data = {})
@@ -14,9 +14,9 @@ def initialize(tx, extra_data = {})
1414
@cell_deps_attrs = []
1515
@witnesses_attrs = []
1616
@header_deps_attrs = []
17+
@output_account_books_attrs = []
1718
@lock_script_attrs = Set.new
1819
@addresses_attrs = Set.new
19-
@account_books_attrs = Set.new
2020
@type_script_attrs = Set.new
2121
end
2222

@@ -69,7 +69,7 @@ def prepare_cell_outputs_params
6969
cell_type = CkbUtils.cell_type(output.type, output_data)
7070
@lock_script_attrs << output.lock.to_h.merge({ script_hash: output.lock.compute_hash })
7171
@addresses_attrs << { address_hash: CkbUtils.generate_address(output.lock), lock_hash: output.lock.compute_hash }
72-
@account_books_attrs << { lock_script_hash: output.lock.compute_hash, tx_hash: transaction.hash }
72+
@output_account_books_attrs << { lock_script_hash: output.lock.compute_hash, tx_hash: transaction.hash, capacity: output.capacity }
7373
@type_script_attrs << output.type.to_h.merge({ script_hash: output.type.compute_hash }) if output.type.present?
7474
@cell_outputs_attrs <<
7575
{

app/models/ckb_sync/transactions.rb

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ def import
2727
cell_deps_attrs = []
2828
witnesses_attrs = []
2929
header_deps_attrs = []
30+
input_account_books_attrs = []
31+
output_account_books_attrs = []
3032
lock_script_attrs = Set.new
3133
addresses_attrs = Set.new
3234
type_script_attrs = Set.new
33-
account_books_attrs = Set.new
3435

3536
group_parsers.each do |parser|
3637
tx_attrs << parser.tx_attr
@@ -40,10 +41,10 @@ def import
4041
cell_deps_attrs.concat(parser.cell_deps_attrs)
4142
header_deps_attrs.concat(parser.header_deps_attrs)
4243
cell_inputs_attrs.concat(parser.cell_inputs_attrs)
44+
output_account_books_attrs.concat(parser.output_account_books_attrs)
4345
lock_script_attrs.merge(parser.lock_script_attrs)
4446
addresses_attrs.merge(parser.addresses_attrs)
4547
type_script_attrs.merge(parser.type_script_attrs)
46-
account_books_attrs.merge(parser.account_books_attrs)
4748
end
4849
ApplicationRecord.transaction do
4950
tx_returnings = CkbTransaction.upsert_all(tx_attrs, unique_by: %i[tx_status tx_hash], returning: %i[id tx_hash])
@@ -61,11 +62,7 @@ def import
6162
type_script_returnings = TypeScript.upsert_all(type_script_attrs.to_a, unique_by: :script_hash, returning: %i[id script_hash])
6263
type_script_mappings = type_script_returnings.rows.to_h { |id, script_hash| [script_hash, id] }
6364
end
64-
new_account_books_attrs =
65-
account_books_attrs.to_a.map do |attr|
66-
{ ckb_transaction_id: tx_mappings[attr[:tx_hash]], address_id: address_mappings[attr[:lock_script_hash]] }
67-
end
68-
AccountBook.upsert_all(new_account_books_attrs, unique_by: %i[address_id ckb_transaction_id])
65+
6966
new_cell_outputs_attrs =
7067
cell_outputs_attrs.map do |attr|
7168
attr.merge({ ckb_transaction_id: tx_mappings[attr[:tx_hash]], lock_script_id: lock_script_mappings[attr[:lock_script_hash]],
@@ -100,25 +97,45 @@ def import
10097
input_conditions = cell_inputs_attrs.filter do |input|
10198
input[:previous_tx_hash] != CellOutput::SYSTEM_TX_HASH
10299
end.map { |input| { tx_hash: input[:previous_tx_hash], cell_index: input[:previous_index] } }
103-
input_returnings = batch_query_outputs(input_conditions, %i[id cell_type tx_hash cell_index capacity])
104-
input_mappings = input_returnings.to_h { |id, cell_type, tx_hash, cell_index| ["#{tx_hash}-#{cell_index}", "#{cell_type}-#{id}"] }
100+
input_returnings = batch_query_outputs(input_conditions, %i[id cell_type tx_hash cell_index address_id capacity])
101+
input_mappings = input_returnings.to_h { |id, cell_type, tx_hash, cell_index, address_id, capacity| ["#{tx_hash}-#{cell_index}", { id:, cell_type:, address_id:, capacity: }] }
105102
new_cell_inputs_attrs =
106103
cell_inputs_attrs.map do |attr|
107104
attr[:ckb_transaction_id] = tx_mappings[attr[:tx_hash]]
108105
if attr[:previous_tx_hash] != CellOutput::SYSTEM_TX_HASH && input_mappings["#{attr[:previous_tx_hash]}-#{attr[:previous_index]}"].present?
109-
cell_type, previous_cell_output_id = input_mappings["#{attr[:previous_tx_hash]}-#{attr[:previous_index]}"].split("-")
110-
attr[:previous_cell_output_id] = previous_cell_output_id
111-
attr[:cell_type] = cell_type
106+
input_hash = input_mappings["#{attr[:previous_tx_hash]}-#{attr[:previous_index]}"]
107+
attr[:previous_cell_output_id] = input_hash[:id]
108+
attr[:cell_type] = input_hash[:cell_type]
109+
input_account_books_attrs << { ckb_transaction_id: attr[:ckb_transaction_id], address_id: input_hash[:address_id], capacity: input_hash[:capacity] }
112110
end
113111
attr.except(:tx_hash)
114112
end
115113
CellInput.upsert_all(new_cell_inputs_attrs, unique_by: %i[ckb_transaction_id index])
114+
new_output_account_books_attrs =
115+
output_account_books_attrs.map do |attr|
116+
{ ckb_transaction_id: tx_mappings[attr[:tx_hash]], address_id: address_mappings[attr[:lock_script_hash]], capacity: attr[:capacity] }
117+
end
118+
account_books_attrs = calculate_income(new_output_account_books_attrs, input_account_books_attrs)
119+
AccountBook.upsert_all(account_books_attrs, unique_by: %i[address_id ckb_transaction_id])
116120
end
117121
end
118122
end
119123

120124
private
121125

126+
def calculate_income(outputs, inputs)
127+
grouped_outputs = outputs.group_by { |o| [o[:ckb_transaction_id], o[:address_id]] }
128+
grouped_inputs = inputs.group_by { |i| [i[:ckb_transaction_id], i[:address_id]] }
129+
130+
all_keys = (grouped_outputs.keys + grouped_inputs.keys).uniq
131+
132+
all_keys.map do |key|
133+
out_cap = grouped_outputs[key]&.sum { |o| o[:capacity] } || 0
134+
in_cap = grouped_inputs[key]&.sum { |i| i[:capacity] } || 0
135+
{ address_id: key[1], ckb_transaction_id: key[0], income: out_cap - in_cap }
136+
end
137+
end
138+
122139
def batch_query_outputs(conditions, returnings = %i[id cell_type tx_hash cell_index])
123140
relation = CellOutput.none
124141

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class AddIncomeToAccountBook < ActiveRecord::Migration[7.0]
2+
def change
3+
execute("SET statement_timeout = 0;")
4+
add_column :account_books, :income, :decimal, precision: 30
5+
add_column :account_books, :block_number, :bigint
6+
add_column :account_books, :tx_index, :integer
7+
8+
add_index :account_books, [:block_number, :tx_index]
9+
end
10+
end

db/structure.sql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,10 @@ SET default_table_access_method = heap;
324324
CREATE TABLE public.account_books (
325325
id bigint NOT NULL,
326326
address_id bigint,
327-
ckb_transaction_id bigint
327+
ckb_transaction_id bigint,
328+
income numeric(30,0),
329+
block_number bigint,
330+
tx_index integer
328331
);
329332

330333

@@ -4719,6 +4722,13 @@ CREATE INDEX idx_cell_inputs_on_previous_tx_hash_and_previous_index ON public.ce
47194722
CREATE UNIQUE INDEX index_account_books_on_address_id_and_ckb_transaction_id ON public.account_books USING btree (address_id, ckb_transaction_id);
47204723

47214724

4725+
--
4726+
-- Name: index_account_books_on_block_number_and_tx_index; Type: INDEX; Schema: public; Owner: -
4727+
--
4728+
4729+
CREATE INDEX index_account_books_on_block_number_and_tx_index ON public.account_books USING btree (block_number, tx_index);
4730+
4731+
47224732
--
47234733
-- Name: index_account_books_on_ckb_transaction_id; Type: INDEX; Schema: public; Owner: -
47244734
--
@@ -6389,6 +6399,7 @@ INSERT INTO "schema_migrations" (version) VALUES
63896399
('20250108053433'),
63906400
('20250126022459'),
63916401
('20250218062041'),
6392-
('20250311084903');
6402+
('20250311084903'),
6403+
('20250318021630');
63936404

63946405

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace :migration do
2+
desc "Usage: RAILS_ENV=production bundle exec rake migration:fill_account_book_block_number_and_tx_index[0,1000000]"
3+
task :fill_account_book_block_number_and_tx_index, %i[start_block end_block] => :environment do |_, args|
4+
$missed_tx_ids = []
5+
(args[:start_block].to_i..args[:end_block].to_i).to_a.each do |block_number|
6+
attrs = Set.new
7+
CkbTransaction.includes(:inputs, :outputs).where(block_number:).where(is_cellbase: false).each do |tx|
8+
outputs = tx.outputs.pluck(:address_id, :capacity).group_by { |item| item[0] }.
9+
transform_values { |values| values.sum { |v| v[1] } }
10+
inputs = tx.inputs.pluck(:address_id, :capacity).group_by { |item| item[0] }.
11+
transform_values { |values| values.sum { |v| v[1] } }
12+
address_ids = (outputs.keys + inputs.keys).uniq
13+
exists = ensure_all_data_exists(address_ids, tx.id)
14+
if exists
15+
address_ids.each do |address_id|
16+
income = (outputs[address_id] || 0) - (inputs[address_id] || 0)
17+
attrs << { address_id:, ckb_transaction_id: tx.id, income:, block_number: tx.block_number, tx_index: tx.tx_index }
18+
end
19+
else
20+
$missed_tx_ids << tx.id
21+
end
22+
end
23+
AccountBook.upsert_all(attrs.to_a, unique_by: %i[address_id ckb_transaction_id]) if attrs.present?
24+
end
25+
26+
puts $missed_tx_ids.join(",")
27+
puts "done"
28+
end
29+
def ensure_all_data_exists(address_ids, tx_id)
30+
data =
31+
address_ids.map do |address_id|
32+
{ address_id:, ckb_transaction_id: tx_id }
33+
end
34+
query_conditions = data.map { |d| "(address_id = #{d[:address_id]} AND ckb_transaction_id = #{d[:ckb_transaction_id]})" }.join(" OR ")
35+
existing_records = AccountBook.where(query_conditions).pluck(:address_id, :ckb_transaction_id)
36+
data.map(&:values).to_set.subset?(existing_records.to_set)
37+
end
38+
end

0 commit comments

Comments
 (0)