From 66aafa6fcb656c7fcfc43989b826b3891fda2562 Mon Sep 17 00:00:00 2001 From: Rabbit Date: Mon, 2 Dec 2024 19:17:58 +0800 Subject: [PATCH 01/11] Issue 797 (#2302) * chore: update dalli client TTL conf * feat: add knowledge size to daily statistics --- app/models/daily_statistic.rb | 9 ++++++++- app/serializers/daily_statistic_serializer.rb | 4 ++++ app/services/charts/daily_statistic_generator.rb | 2 +- ...41202072604_add_knowledge_size_to_daily_statistics.rb | 5 +++++ db/structure.sql | 7 +++++-- test/services/charts/daily_statistic_generator_test.rb | 8 ++++++++ 6 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20241202072604_add_knowledge_size_to_daily_statistics.rb diff --git a/app/models/daily_statistic.rb b/app/models/daily_statistic.rb index a94bc644c..ff2d11f17 100644 --- a/app/models/daily_statistic.rb +++ b/app/models/daily_statistic.rb @@ -5,7 +5,7 @@ class DailyStatistic < ApplicationRecord transactions_count addresses_count total_dao_deposit live_cells_count dead_cells_count avg_hash_rate avg_difficulty uncle_rate total_depositors_count address_balance_distribution total_tx_fee occupied_capacity daily_dao_deposit daily_dao_depositors_count circulation_ratio daily_dao_withdraw nodes_count circulating_supply burnt locked_capacity treasury_amount mining_reward - deposit_compensation liquidity created_at_unixtimestamp ckb_hodl_wave holder_count + deposit_compensation liquidity created_at_unixtimestamp ckb_hodl_wave holder_count knowledge_size ).freeze MILLISECONDS_IN_DAY = BigDecimal(24 * 60 * 60 * 1000) GENESIS_TIMESTAMP = 1573852190812 @@ -239,6 +239,12 @@ def liquidity tip_parse_dao.c_i - MarketData::BURN_QUOTA - treasury_amount.to_i end + define_logic :knowledge_size do + tip_dao = current_tip_block.dao + tip_parse_dao = CkbUtils.parse_dao(tip_dao) + tip_parse_dao.u_i - MarketData::BURN_QUOTA * 0.6 + end + define_logic :circulating_supply do MarketData.new(indicator: "circulating_supply", tip_block_number: current_tip_block.number, unit: "shannon").call @@ -568,6 +574,7 @@ def aggron_first_day? # locked_capacity :decimal(30, ) # ckb_hodl_wave :jsonb # holder_count :integer +# knowledge_size :decimal(30, ) # # Indexes # diff --git a/app/serializers/daily_statistic_serializer.rb b/app/serializers/daily_statistic_serializer.rb index 7baa598a5..dbd75c091 100644 --- a/app/serializers/daily_statistic_serializer.rb +++ b/app/serializers/daily_statistic_serializer.rb @@ -134,4 +134,8 @@ class DailyStatisticSerializer } do |object| object.holder_count.to_s end + + attribute :knowledge_size, if: Proc.new { |_record, params| + params.present? && params[:indicator].include?("knowledge_size") + } end diff --git a/app/services/charts/daily_statistic_generator.rb b/app/services/charts/daily_statistic_generator.rb index 29a9544ef..0d68f26e0 100644 --- a/app/services/charts/daily_statistic_generator.rb +++ b/app/services/charts/daily_statistic_generator.rb @@ -32,7 +32,7 @@ def updated_attrs } others = %i{ block_timestamp transactions_count addresses_count daily_dao_withdraw - average_deposit_time mining_reward + average_deposit_time mining_reward knowledge_size treasury_amount estimated_apc live_cells_count dead_cells_count avg_hash_rate avg_difficulty uncle_rate address_balance_distribution total_tx_fee occupied_capacity daily_dao_deposit total_supply block_time_distribution diff --git a/db/migrate/20241202072604_add_knowledge_size_to_daily_statistics.rb b/db/migrate/20241202072604_add_knowledge_size_to_daily_statistics.rb new file mode 100644 index 000000000..7ee48261a --- /dev/null +++ b/db/migrate/20241202072604_add_knowledge_size_to_daily_statistics.rb @@ -0,0 +1,5 @@ +class AddKnowledgeSizeToDailyStatistics < ActiveRecord::Migration[7.0] + def change + add_column :daily_statistics, :knowledge_size, :decimal, precision: 30 + end +end diff --git a/db/structure.sql b/db/structure.sql index b0ee52b1a..b37f2e718 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1512,7 +1512,8 @@ CREATE TABLE public.daily_statistics ( nodes_count integer, locked_capacity numeric(30,0), ckb_hodl_wave jsonb, - holder_count integer + holder_count integer, + knowledge_size numeric(30,0) ); @@ -5945,4 +5946,6 @@ INSERT INTO "schema_migrations" (version) VALUES ('20240823071323'), ('20240823071420'), ('20240902025657'), -('20240904043807'); +('20240904043807'), +('20241202072604'); + diff --git a/test/services/charts/daily_statistic_generator_test.rb b/test/services/charts/daily_statistic_generator_test.rb index b876f8362..13b04281e 100644 --- a/test/services/charts/daily_statistic_generator_test.rb +++ b/test/services/charts/daily_statistic_generator_test.rb @@ -444,6 +444,14 @@ class DailyStatisticGeneratorTest < ActiveSupport::TestCase assert_equal total_supply_temp, total_supply end + test "it should get knowledge_size" do + tip_dao = @current_tip_block.dao + tip_parse_dao = CkbUtils.parse_dao(tip_dao) + knowledge_size_temp = tip_parse_dao.u_i - MarketData::BURN_QUOTA * 0.6 + knowledge_size = Charts::DailyStatisticGenerator.new(@datetime).call.knowledge_size + assert_equal knowledge_size_temp, knowledge_size + end + test "it should get epoch_length_distribution" do max_n = 1700 ranges = (700..max_n).step(100).map { |n| [n, n + 100] } From 82dd84fed760d9d742c6474a435ed6440ade97db Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Wed, 4 Dec 2024 15:59:18 +0900 Subject: [PATCH 02/11] Refactor contract (#2306) * feat: adjust contract and cell_dependencies table * feat: adjust api Signed-off-by: Miles Zhang * feat: use task fix data Signed-off-by: Miles Zhang * feat: comment code Signed-off-by: Miles Zhang * feat: sync cell dependency Signed-off-by: Miles Zhang * feat: add contract_analyzed to cell_dependencies Signed-off-by: Miles Zhang * feat: use worker to analyze contract Signed-off-by: Miles Zhang * fix: use new cell dependency unique index Signed-off-by: Miles Zhang * feat: add index to contract_analyzed Signed-off-by: Miles Zhang * chore: set statement_timeout for migration Signed-off-by: Miles Zhang * feat: enhance analyze contract worker Signed-off-by: Miles Zhang * test: fix test Signed-off-by: Miles Zhang * fix: some contract's script count is too many Signed-off-by: Miles Zhang * feat: stop create contract in node processor Signed-off-by: Miles Zhang * feat: fill contract info task Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- app/controllers/api/v2/scripts_controller.rb | 126 +++-- .../api/v2/statistics_controller.rb | 4 +- app/models/cell_dependency.rb | 27 +- app/models/cell_deps_out_point.rb | 23 + app/models/cell_output.rb | 5 +- app/models/ckb_sync/api.rb | 4 +- .../ckb_sync/new_node_data_processor.rb | 108 ++-- app/models/ckb_sync/transactions.rb | 2 +- app/models/ckb_transaction.rb | 4 +- app/models/contract.rb | 57 ++- app/models/lock_script.rb | 33 +- app/models/type_script.rb | 28 +- app/serializers/ckb_transaction_serializer.rb | 2 +- app/utils/ckb_utils.rb | 1 - .../v2/scripts/ckb_transactions.json.jbuilder | 2 +- .../v2/scripts/deployed_cells.json.jbuilder | 2 +- .../v2/scripts/referring_cells.json.jbuilder | 2 +- ...ze_contract_from_cell_dependency_worker.rb | 100 ++++ app/workers/contract_statistic_worker.rb | 49 +- .../generate_cell_dependencies_worker.rb | 3 +- .../generate_udt_holder_allocation_worker.rb | 2 +- config/settings.testnet.yml | 6 +- ...3071323_add_unique_index_to_lock_script.rb | 9 +- ...3071420_add_unique_index_to_type_script.rb | 9 +- ...hange_ckb_transaction_confirmation_time.rb | 3 +- ...241105070340_create_cell_deps_out_point.rb | 14 + ...ve_implicit_column_from_cell_dependency.rb | 8 + ...022_add_type_hash_data_hash_to_contract.rb | 9 + ...114074433_add_unique_index_to_contracts.rb | 5 + ...4652_reset_cell_dependency_unique_index.rb | 9 + ...5_add_sorted_index_to_cell_dependencies.rb | 11 + ...dd_contract_analyzed_to_cell_dependency.rb | 5 + ...tract_analyzed_index_to_cell_dependency.rb | 7 + db/structure.sql | 112 +++- lib/scheduler.rb | 4 + ..._dependency_block_number_and_tx_index.rake | 46 ++ .../migration/fill_cell_deps_out_point.rake | 37 ++ lib/tasks/migration/fill_contracts_info.rake | 483 ++++++++++++++++++ lib/tasks/migration/init_contracts.rake | 54 -- .../api/v2/scripts_controller_test.rb | 11 +- .../api/v2/statistics_controller_test.rb | 2 +- test/factories/cell_dependency.rb | 2 +- test/factories/cell_deps_out_point.rb | 6 + test/factories/contract.rb | 8 +- test/models/cell_dependency_test.rb | 20 +- .../ckb_sync/node_data_processor_test.rb | 11 + test/models/contract_test.rb | 18 +- test/models/deployed_cell_test.rb | 340 ++++++------ test/models/script_test.rb | 56 +- test/models/script_transaction_test.rb | 118 ++--- vcr_fixtures/vcr_cassettes/blocks/33.yml | 73 +-- 51 files changed, 1438 insertions(+), 642 deletions(-) create mode 100644 app/models/cell_deps_out_point.rb create mode 100644 app/workers/analyze_contract_from_cell_dependency_worker.rb create mode 100644 db/migrate/20241105070340_create_cell_deps_out_point.rb create mode 100644 db/migrate/20241105070619_remove_implicit_column_from_cell_dependency.rb create mode 100644 db/migrate/20241106062022_add_type_hash_data_hash_to_contract.rb create mode 100644 db/migrate/20241114074433_add_unique_index_to_contracts.rb create mode 100644 db/migrate/20241119014652_reset_cell_dependency_unique_index.rb create mode 100644 db/migrate/20241121073245_add_sorted_index_to_cell_dependencies.rb create mode 100644 db/migrate/20241125100650_add_contract_analyzed_to_cell_dependency.rb create mode 100644 db/migrate/20241129000339_add_contract_analyzed_index_to_cell_dependency.rb create mode 100644 lib/tasks/migration/fill_cell_dependency_block_number_and_tx_index.rake create mode 100644 lib/tasks/migration/fill_cell_deps_out_point.rake create mode 100644 lib/tasks/migration/fill_contracts_info.rake delete mode 100644 lib/tasks/migration/init_contracts.rake create mode 100644 test/factories/cell_deps_out_point.rb diff --git a/app/controllers/api/v2/scripts_controller.rb b/app/controllers/api/v2/scripts_controller.rb index 4b83752eb..3332a8fe0 100644 --- a/app/controllers/api/v2/scripts_controller.rb +++ b/app/controllers/api/v2/scripts_controller.rb @@ -3,88 +3,87 @@ 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 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? + + contract_ids = @contracts.map { |contract| contract.id } + contract_cell_ids = CellDepsOutPoint.list_contract_cell_ids_by_contract(contract_ids) + base_query = CkbTransaction.joins(:cell_dependencies). + where(cell_dependencies: { contract_cell_id: contract_cell_ids }). + order("cell_dependencies.block_number DESC, cell_dependencies.tx_index DESC"). + limit(10000) + @ckb_transactions = CkbTransaction.from("(#{base_query.to_sql}) AS ckb_transactions"). + order("block_number DESC, tx_index DESC"). + page(@page). + per(@page_size) end def deployed_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 - @deployed_cells = - if @contract.deployed_cells_count.zero? - CellOutput.none - else - @contract.deployed_cell_outputs.live.page(@page).per(@page_size) - end + + @deployed_cells = 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 - - @referring_cells = sort_referring_cells(scope).page(@page).per(@page_size) + scope = Contract.referring_cells_query(@contracts). + order("block_timestamp DESC, cell_index DESC"). + limit(10000) + 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 = + CellOutput.from("(#{scope.to_sql}) AS cell_outputs"). + order("block_timestamp DESC, cell_index DESC"). + 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 + sum_hash = + @contracts.inject({ + capacity_of_deployed_cells: 0, + capacity_of_referring_cells: 0, + count_of_transactions: 0, + count_of_deployed_cells: 0, + count_of_referring_cells: 0, + }) do |sum, contract| + sum[:capacity_of_deployed_cells] += contract.total_deployed_cells_capacity + sum[:capacity_of_referring_cells] += contract.total_referring_cells_capacity + sum[:count_of_transactions] += contract.ckb_transactions_count + sum[:count_of_deployed_cells] += 1 + sum[:count_of_referring_cells] += contract.referring_cells_count + sum end - 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, - } + id: @contracts.first.type_hash, + code_hash: params[:code_hash], + hash_type: params[:hash_type], + script_type: @contracts.first.is_lock_script ? "LockScript" : "TypeScript", + }.merge(sum_hash) end def set_page_and_page_size @@ -92,15 +91,14 @@ def set_page_and_page_size @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.where(type_hash: params[:code_hash]) + end end def sort_referring_cells(records) diff --git a/app/controllers/api/v2/statistics_controller.rb b/app/controllers/api/v2/statistics_controller.rb index 087fa6f3c..7c0b396d1 100644 --- a/app/controllers/api/v2/statistics_controller.rb +++ b/app/controllers/api/v2/statistics_controller.rb @@ -14,10 +14,10 @@ def transaction_fees end def contract_resource_distributed - contracts = Contract.filter_nil_hash_type + contracts = Contract.active if params[:code_hashes].present? hashes = params[:code_hashes].split(",") - contracts = contracts.where(code_hash: hashes) + contracts = contracts.where(type_hash: hashes) end if stale?(contracts) expires_in 30.minutes, public: true diff --git a/app/models/cell_dependency.rb b/app/models/cell_dependency.rb index ae8dc9100..0729d5086 100644 --- a/app/models/cell_dependency.rb +++ b/app/models/cell_dependency.rb @@ -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) } + belongs_to :cell_deps_out_point, foreign_key: :contract_cell_id, primary_key: :contract_cell_id, optional: true + + enum :dep_type, %i[code dep_group] def self.refresh_implicit connection.execute "SELECT update_cell_dependencies_implicit();" @@ -16,9 +14,9 @@ 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 end @@ -28,17 +26,20 @@ def to_raw # 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 +# contract_analyzed :boolean default(FALSE) # # 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) +# index_cell_dependencies_on_block_number_and_tx_index (block_number,tx_index) +# index_cell_dependencies_on_contract_analyzed (contract_analyzed) +# index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type (ckb_transaction_id,contract_cell_id,dep_type) UNIQUE +# index_on_cell_dependencies_contract_cell_block_tx (contract_cell_id,block_number DESC,tx_index DESC) # diff --git a/app/models/cell_deps_out_point.rb b/app/models/cell_deps_out_point.rb new file mode 100644 index 000000000..d6d28258b --- /dev/null +++ b/app/models/cell_deps_out_point.rb @@ -0,0 +1,23 @@ +class CellDepsOutPoint < ApplicationRecord + belongs_to :contract, foreign_key: :deployed_cell_output_id, primary_key: :deployed_cell_output_id, optional: true + has_many :cell_dependencies, foreign_key: :contract_cell_id, primary_key: :contract_cell_id + + scope :list_contract_cell_ids_by_contract, ->(contract_ids) { joins(:contract).where(contracts: { id: contract_ids }).pluck(:contract_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 +# diff --git a/app/models/cell_output.rb b/app/models/cell_output.rb index 228d00722..d86a22b05 100644 --- a/app/models/cell_output.rb +++ b/app/models/cell_output.rb @@ -42,8 +42,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 @@ -108,6 +108,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 (?) OR type_script_id IN (?)", lock_script_ids, type_script_ids) } before_create :setup_address diff --git a/app/models/ckb_sync/api.rb b/app/models/ckb_sync/api.rb index 168bafe65..578879118 100644 --- a/app/models/ckb_sync/api.rb +++ b/app/models/ckb_sync/api.rb @@ -75,7 +75,7 @@ def spore_cluster_code_hashes if mode == CKB::MODE::MAINNET [Settings.spore_cluster1_code_hash] else - [Settings.spore_cluster1_code_hash, Settings.spore_cluster2_code_hash, Settings.spore_cluster3_code_hash] + [Settings.spore_cluster1_code_hash, Settings.spore_cluster2_code_hash] end end @@ -83,7 +83,7 @@ def spore_cell_code_hashes if mode == CKB::MODE::MAINNET [Settings.spore_cell1_code_hash] else - [Settings.spore_cell1_code_hash, Settings.spore_cell2_code_hash, Settings.spore_cell3_code_hash] + [Settings.spore_cell1_code_hash, Settings.spore_cell2_code_hash] end end diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index a5f60d51c..bebdd415d 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -59,7 +59,8 @@ def process_block(node_block, refresh_balance: true) inputs = @inputs = {} outputs = @outputs = {} outputs_data = @outputs_data = {} - @ckb_txs = build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data).to_a + cell_deps = {} + @ckb_txs = build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data, cell_deps).to_a benchmark :build_udts!, local_block, outputs, outputs_data tags = [] @@ -74,7 +75,7 @@ def process_block(node_block, refresh_balance: true) addrs_changes = Hash.new { |hash, key| hash[key] = {} } input_capacities, output_capacities = benchmark :build_cells_and_locks!, local_block, node_block, ckb_txs, inputs, outputs, - tags, udt_address_ids, dao_address_ids, contained_udt_ids, contained_address_ids, addrs_changes, token_transfer_ckb_tx_ids + tags, udt_address_ids, dao_address_ids, contained_udt_ids, contained_address_ids, addrs_changes, token_transfer_ckb_tx_ids, cell_deps # update explorer data benchmark :update_ckb_txs_rel_and_fee, ckb_txs, tags, input_capacities, output_capacities, udt_address_ids, @@ -92,7 +93,7 @@ def process_block(node_block, refresh_balance: true) async_update_udt_infos(local_block) flush_inputs_outputs_caches(local_block) generate_statistics_data(local_block) - generate_deployed_cells_and_referring_cells(local_block) + # generate_deployed_cells_and_referring_cells(local_block) detect_cota_infos(local_block) detect_token_transfer(token_transfer_ckb_tx_ids) detect_bitcoin_transactions(local_block) @@ -785,7 +786,7 @@ def update_ckb_txs_rel_and_fee( def build_cells_and_locks!( local_block, node_block, ckb_txs, inputs, outputs, tags, udt_address_ids, - dao_address_ids, contained_udt_ids, contained_addr_ids, addrs_changes, token_transfer_ckb_tx_ids + dao_address_ids, contained_udt_ids, contained_addr_ids, addrs_changes, token_transfer_ckb_tx_ids, cell_deps ) cell_outputs_attributes = [] cell_inputs_attributes = [] @@ -800,43 +801,43 @@ def build_cells_and_locks!( lock_scripts_attributes.map! do |attr| attr.merge!(created_at: Time.current, updated_at: Time.current) end - lock_script_ids = LockScript.upsert_all(lock_scripts_attributes, unique_by: :script_hash, returning: [:id]) - - lock_script_ids.each do |row| - lock_script_id = row["id"] - lock_script = LockScript.find lock_script_id - contract = Contract.find_by code_hash: lock_script.code_hash - temp_hash = { script_hash: lock_script&.script_hash, is_contract: false } - if contract - temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id - else - contract = Contract.create code_hash: lock_script.script_hash - temp_hash = temp_hash.merge contract_id: contract.id - end - # script = Script.find_or_create_by temp_hash - # lock_script.update script_id: script.id - end + LockScript.upsert_all(lock_scripts_attributes, unique_by: :script_hash, returning: [:id]) + + # lock_script_ids.each do |row| + # lock_script_id = row["id"] + # lock_script = LockScript.find lock_script_id + # contract = Contract.find_by code_hash: lock_script.code_hash + # temp_hash = { script_hash: lock_script&.script_hash, is_contract: false } + # if contract + # temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id + # else + # contract = Contract.create code_hash: lock_script.script_hash + # temp_hash = temp_hash.merge contract_id: contract.id + # end + # # script = Script.find_or_create_by temp_hash + # # lock_script.update script_id: script.id + # end end if type_scripts_attributes.present? type_scripts_attributes.map! do |attr| attr.merge!(created_at: Time.current, updated_at: Time.current) end - type_script_ids = TypeScript.upsert_all(type_scripts_attributes, unique_by: :script_hash, returning: [:id]) - type_script_ids.each do |row| - type_script_id = row["id"] - type_script = TypeScript.find(type_script_id) - temp_hash = { script_hash: type_script&.script_hash, is_contract: false } - contract = Contract.find_by code_hash: type_script.code_hash - if contract - temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id - else - contract = Contract.create code_hash: type_script.script_hash - temp_hash = temp_hash.merge contract_id: contract.id - end - # script = Script.find_or_create_by temp_hash - # type_script.update script_id: script.id - end + TypeScript.upsert_all(type_scripts_attributes, unique_by: :script_hash, returning: [:id]) + # type_script_ids.each do |row| + # type_script_id = row["id"] + # type_script = TypeScript.find(type_script_id) + # temp_hash = { script_hash: type_script&.script_hash, is_contract: false } + # contract = Contract.find_by code_hash: type_script.code_hash + # if contract + # temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id + # else + # contract = Contract.create code_hash: type_script.script_hash + # temp_hash = temp_hash.merge contract_id: contract.id + # end + # # script = Script.find_or_create_by temp_hash + # # type_script.update script_id: script.id + # end end build_addresses!(outputs, local_block) # prepare script ids for insert cell_outputs @@ -866,6 +867,34 @@ def build_cells_and_locks!( end end + hash2index = {} + hash2id = {} + ckb_txs.each do |t| + hash2id["0#{t['tx_hash'][1..]}"] = t["id"] + hash2index["0#{t['tx_hash'][1..]}"] = t["tx_index"] + end + + cell_deps_attrs = [] + cell_deps.each do |tx_hash, cell_deps| + txid = hash2id[tx_hash] + tx_index = hash2index[tx_hash] + + cell_deps.each do |cell_dep| + cell_deps_attrs << + { + ckb_transaction_id: txid, + dep_type: cell_dep.dep_type, + contract_cell_id: CellOutput.find_by_pointer(cell_dep.out_point.tx_hash, cell_dep.out_point.index).id, + block_number: local_block.number, + tx_index:, + } + end + end + if cell_deps_attrs.present? + CellDependency.upsert_all(cell_deps_attrs, + unique_by: %i[ckb_transaction_id contract_cell_id dep_type]) + end + prev_outputs = nil build_cell_inputs(inputs, ckb_txs, local_block.id, cell_inputs_attributes, prev_cell_outputs_attributes, input_capacities, tags, udt_address_ids, dao_address_ids, contained_udt_ids, contained_addr_ids, @@ -881,8 +910,8 @@ def build_cells_and_locks!( record_timestamps: true) end - ScriptTransaction.create_from_scripts TypeScript.where(id: type_script_ids) - ScriptTransaction.create_from_scripts LockScript.where(id: lock_script_ids) + # ScriptTransaction.create_from_scripts TypeScript.where(id: type_script_ids) + # ScriptTransaction.create_from_scripts LockScript.where(id: lock_script_ids) [input_capacities, output_capacities] end @@ -1239,7 +1268,7 @@ def cell_input_attributes(input, ckb_transaction_id, local_block_id, end end - def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data) + def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data, cell_deps) cycles = CkbSync::Api.instance.get_block_cycles node_block.header.hash ckb_transactions_attributes = [] hashes = [] @@ -1251,6 +1280,7 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da attrs[:cycles] = tx_index > 0 ? cycles[tx_index - 1]&.hex : nil end header_deps[tx.hash] = tx.header_deps + cell_deps[tx.hash] = tx.cell_deps witnesses[tx.hash] = tx.witnesses ckb_transactions_attributes << attrs hashes << tx.hash @@ -1268,7 +1298,7 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da CkbTransaction.where("tx_hash IN (#{binary_hashes}) AND tx_status = 0").update_all tx_status: "committed" txs = CkbTransaction.upsert_all(ckb_transactions_attributes, unique_by: %i[tx_status tx_hash], - returning: %w(id tx_hash block_timestamp created_at)) + returning: %w(id tx_hash tx_index block_timestamp created_at)) if pending_txs.any? hash_to_pool_times = pending_txs.to_h diff --git a/app/models/ckb_sync/transactions.rb b/app/models/ckb_sync/transactions.rb index 9f2ca8d7d..9e9337dae 100644 --- a/app/models/ckb_sync/transactions.rb +++ b/app/models/ckb_sync/transactions.rb @@ -95,7 +95,7 @@ def import cell_deps_attrs.map do |attr| { ckb_transaction_id: tx_mappings[attr[:tx_hash]], contract_cell_id: cell_dep_mappings["#{attr[:out_point_tx_hash]}-#{attr[:out_point_index]}"], dep_type: attr[:dep_type] } end.filter { |attr| !attr[:contract_cell_id].nil? } - CellDependency.upsert_all(new_cell_deps_attrs, unique_by: %i[ckb_transaction_id contract_cell_id]) if new_cell_deps_attrs.present? + CellDependency.upsert_all(new_cell_deps_attrs, unique_by: %i[ckb_transaction_id contract_cell_id dep_type]) if new_cell_deps_attrs.present? input_conditions = cell_inputs_attrs.filter do |input| input[:previous_tx_hash] != CellOutput::SYSTEM_TX_HASH diff --git a/app/models/ckb_transaction.rb b/app/models/ckb_transaction.rb index aecd211ea..a8ba683a1 100644 --- a/app/models/ckb_transaction.rb +++ b/app/models/ckb_transaction.rb @@ -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) @@ -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, diff --git a/app/models/contract.rb b/app/models/contract.rb index ccd01a011..91e366be3 100644 --- a/app/models/contract.rb +++ b/app/models/contract.rb @@ -1,24 +1,29 @@ class Contract < ApplicationRecord - has_many :scripts - has_many :deployed_cells - has_many :deployed_cell_outputs, through: :deployed_cells, source: :cell_output - has_many :referring_cells - has_many :referring_cell_outputs, through: :referring_cells, source: :cell_output - has_many :cell_dependencies - has_many :ckb_transactions, through: :cell_dependencies + has_many :cell_deps_out_points, foreign_key: :deployed_cell_output_id, primary_key: :deployed_cell_output_id + has_many :cell_dependencies, through: :cell_deps_out_points + has_one :deployed_cell_output, foreign_key: :deployed_cell_output_id - scope :filter_nil_hash_type, -> { where("hash_type IS NOT null and addresses_count != 0 and total_referring_cells_capacity != 0 and ckb_transactions_count != 0") } + scope :active, -> { where("addresses_count != 0 and total_referring_cells_capacity != 0 and ckb_transactions_count != 0") } - def self.create_initial_data - Contract.transaction do - Script.find_each do |script| - contract = Contract.find_by code_hash: script.script_hash - if contract.blank? - contract = Contract.create code_hash: script.script_hash - end - script.update contract_id: contract.id + def self.referring_cells_query(contracts) + lock_script_hashes = [] + type_script_hashes = [] + contracts.each do |contract| + binary_hashes = CkbUtils.hexes_to_bins_sql([contract.type_hash, contract.data_hash].compact) + if contract.is_lock_script + lock_script_hashes << binary_hashes + elsif contract.is_type_script + type_script_hashes << binary_hashes end end + scope = CellOutput.live + if lock_script_hashes.length > 0 + scope = scope.joins(:lock_script).where("lock_scripts.code_hash IN (#{lock_script_hashes.join(',')})") + end + if type_script_hashes.length > 0 + scope = scope.joins(:type_script).where("type_scripts.code_hash IN (#{type_script_hashes.join(',')})") + end + scope end end @@ -45,14 +50,20 @@ def self.create_initial_data # total_referring_cells_capacity :decimal(30, ) default(0) # addresses_count :integer # h24_ckb_transactions_count :integer +# type_hash :binary +# data_hash :binary +# deployed_cell_output_id :bigint +# is_type_script :boolean +# is_lock_script :boolean # # Indexes # -# index_contracts_on_code_hash (code_hash) -# index_contracts_on_deprecated (deprecated) -# index_contracts_on_hash_type (hash_type) -# index_contracts_on_name (name) -# index_contracts_on_role (role) -# index_contracts_on_symbol (symbol) -# index_contracts_on_verified (verified) +# index_contracts_on_code_hash (code_hash) +# index_contracts_on_deployed_cell_output_id (deployed_cell_output_id) UNIQUE +# index_contracts_on_deprecated (deprecated) +# index_contracts_on_hash_type (hash_type) +# index_contracts_on_name (name) +# index_contracts_on_role (role) +# index_contracts_on_symbol (symbol) +# index_contracts_on_verified (verified) # diff --git a/app/models/lock_script.rb b/app/models/lock_script.rb index 76cc760c7..77984fb53 100644 --- a/app/models/lock_script.rb +++ b/app/models/lock_script.rb @@ -13,43 +13,45 @@ class LockScript < ApplicationRecord validates_presence_of :code_hash attribute :code_hash, :ckb_hash + scope :lock_script, ->(type_hash, data_hash) { where(code_hash: [type_hash, data_hash]) } + def self.process(sdk_lock) lock_hash = sdk_lock.compute_hash address_hash = CkbUtils.generate_address(sdk_lock) - address = Address.create_with(address_hash: address_hash).find_or_create_by!(lock_hash: lock_hash) + address = Address.create_with(address_hash:).find_or_create_by!(lock_hash:) # contract = Contract.create_or_find_by(code_hash: lock.code_hash) # script = Script create_with( script_hash: lock_hash, - address: address + address:, ).find_or_create_by!( code_hash: sdk_lock.code_hash, hash_type: sdk_lock.hash_type, - args: sdk_lock.args + args: sdk_lock.args, ) end def to_node { - args: args, - code_hash: code_hash, - hash_type: hash_type + args:, + code_hash:, + hash_type:, } end - def as_json(options = {}) + def as_json(_options = {}) { - args: args, - code_hash: code_hash, - hash_type: hash_type, - script_hash: script_hash + args:, + code_hash:, + hash_type:, + script_hash:, } end def ckb_transactions - CkbTransaction.where(id: CellOutput.where(lock_script_id: self.id).pluck("ckb_transaction_id", - "consumed_by_id").flatten) + CkbTransaction.where(id: CellOutput.where(lock_script_id: id).pluck("ckb_transaction_id", + "consumed_by_id").flatten) end def cell_output @@ -83,7 +85,8 @@ def lock_info { status: lock_info_status(since_value, tip_epoch), epoch_number: epoch_number.to_s, - epoch_index: since_value_index.to_s, estimated_unlock_time: estimated_unlock_time.strftime("%Q") } + epoch_index: since_value_index.to_s, estimated_unlock_time: estimated_unlock_time.strftime("%Q") + } rescue SinceParser::IncorrectSinceFlagsError nil end @@ -110,7 +113,7 @@ def set_since_epoch_number_and_index(since_value) since_value_index = since_value.index end - return epoch_number, since_value_index + [epoch_number, since_value_index] end def lock_info_status(since_value, tip_epoch) diff --git a/app/models/type_script.rb b/app/models/type_script.rb index bc03e9184..c0173ea2f 100644 --- a/app/models/type_script.rb +++ b/app/models/type_script.rb @@ -10,33 +10,35 @@ class TypeScript < ApplicationRecord validates_presence_of :code_hash attribute :code_hash, :ckb_hash + scope :type_script, ->(type_hash, data_hash) { where(code_hash: [type_hash, data_hash]) } + def self.process(sdk_type) type_hash = sdk_type.compute_hash # contract = Contract.create_or_find_by(code_hash: lock.code_hash) # script = Script create_with( - script_hash: type_hash + script_hash: type_hash, ).find_or_create_by( code_hash: sdk_type.code_hash, hash_type: sdk_type.hash_type, - args: sdk_type.args + args: sdk_type.args, ) end def to_node { - args: args, - code_hash: code_hash, - hash_type: hash_type + args:, + code_hash:, + hash_type:, } end - def as_json(options = {}) + def as_json(_options = {}) { - args: args, - code_hash: code_hash, - hash_type: hash_type, - script_hash: script_hash + args:, + code_hash:, + hash_type:, + script_hash:, } end @@ -50,7 +52,11 @@ def short_code_hash def generate_script_hash self.hash_type ||= "type" - self.script_hash ||= CKB::Types::Script.new(**to_node).compute_hash rescue nil + self.script_hash ||= begin + CKB::Types::Script.new(**to_node).compute_hash + rescue StandardError + nil + end end # @return [Integer] Byte diff --git a/app/serializers/ckb_transaction_serializer.rb b/app/serializers/ckb_transaction_serializer.rb index 8286ba250..e236ecc69 100644 --- a/app/serializers/ckb_transaction_serializer.rb +++ b/app/serializers/ckb_transaction_serializer.rb @@ -11,7 +11,7 @@ class CkbTransactionSerializer end attribute :cell_deps do |o| - o.cell_dependencies.explicit.order("id asc").includes(:cell_output).to_a.map(&:to_raw) + o.cell_dependencies.order("id asc").includes(:cell_output).to_a.map(&:to_raw) end attribute :header_deps do |o| diff --git a/app/utils/ckb_utils.rb b/app/utils/ckb_utils.rb index e99c67917..2ebb5ef3e 100644 --- a/app/utils/ckb_utils.rb +++ b/app/utils/ckb_utils.rb @@ -626,7 +626,6 @@ def self.parse_spore_cluster_data(hex_data) { name: sanitize_string(name), description: sanitize_string(description) } rescue StandardError => e - puts "Error parsing spore cluster data: #{e.message}" { name: nil, description: nil } end diff --git a/app/views/api/v2/scripts/ckb_transactions.json.jbuilder b/app/views/api/v2/scripts/ckb_transactions.json.jbuilder index 9f90eff7f..386cb02e8 100644 --- a/app/views/api/v2/scripts/ckb_transactions.json.jbuilder +++ b/app/views/api/v2/scripts/ckb_transactions.json.jbuilder @@ -26,7 +26,7 @@ json.data do json.rgb_txid tx.rgb_txid end json.meta do - json.total @contract.ckb_transactions_count + json.total @ckb_transactions.total_count json.page_size @page_size.to_i end end diff --git a/app/views/api/v2/scripts/deployed_cells.json.jbuilder b/app/views/api/v2/scripts/deployed_cells.json.jbuilder index ad742d4ea..ddf21033d 100644 --- a/app/views/api/v2/scripts/deployed_cells.json.jbuilder +++ b/app/views/api/v2/scripts/deployed_cells.json.jbuilder @@ -23,7 +23,7 @@ json.data do json.type_script_id deployed_cell.type_script_id end json.meta do - json.total @contract.deployed_cells_count + json.total @deployed_cells.total_count json.page_size @page_size.to_i end end diff --git a/app/views/api/v2/scripts/referring_cells.json.jbuilder b/app/views/api/v2/scripts/referring_cells.json.jbuilder index 4e13e3c26..c496c2e9e 100644 --- a/app/views/api/v2/scripts/referring_cells.json.jbuilder +++ b/app/views/api/v2/scripts/referring_cells.json.jbuilder @@ -23,7 +23,7 @@ json.data do json.type_script_id referring_cell.type_script_id end json.meta do - json.total @contract.referring_cells_count + json.total @referring_cells.total_count json.page_size @page_size.to_i end end diff --git a/app/workers/analyze_contract_from_cell_dependency_worker.rb b/app/workers/analyze_contract_from_cell_dependency_worker.rb new file mode 100644 index 000000000..9c2edd825 --- /dev/null +++ b/app/workers/analyze_contract_from_cell_dependency_worker.rb @@ -0,0 +1,100 @@ +class AnalyzeContractFromCellDependencyWorker + include Sidekiq::Worker + + def perform + cell_deps_out_points_attrs = Set.new + contract_attrs = Set.new + cell_deps_attrs = Set.new + + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(1000).each do |cell_dep| + cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } + + next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? + + ckb_transaction = CkbTransaction.find(cell_dep.ckb_transaction_id) + + type_script_hashes = Set.new + lock_script_hashes = Set.new + + cell_outputs = ckb_transaction.cell_outputs.includes(:type_script, :lock_script).to_a + cell_inputs = ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output) + cell_inputs.each do |input| + lock_script_hashes << input.lock_script.code_hash + type_script_hashes << input.type_script.code_hash if input.type_script + end + + cell_outputs.each do |output| + lock_script_hashes << output.lock_script.code_hash + type_script_hashes << output.type_script.code_hash if output.type_script + end + + case cell_dep.dep_type + when "code" + cell_output = cell_dep.cell_output + cell_deps_out_points_attrs << { + tx_hash: cell_output.tx_hash, + cell_index: cell_output.cell_index, + deployed_cell_output_id: cell_output.id, + contract_cell_id: cell_output.id, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + 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:, + is_lock_script:, + deployed_args: cell_output.type_script&.args, + } + end + + 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 = cell_dep.cell_output + + binary_data = mid_cell.binary_data + # 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| + part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<") + + tx_hash = "0x#{part_tx_hash}" + 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, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + contract_attrs << + { + type_hash: cell_output.type_script&.script_hash, + data_hash: cell_output.data_hash, + deployed_cell_output_id: cell_output.id, + deployed_args: cell_output.type_script&.args, + is_type_script:, + is_lock_script:, + } + end + end + end + end + if cell_deps_out_points_attrs.any? + CellDepsOutPoint.upsert_all(cell_deps_out_points_attrs, + unique_by: %i[contract_cell_id deployed_cell_output_id]) + end + Contract.upsert_all(contract_attrs, unique_by: %i[deployed_cell_output_id]) if contract_attrs.any? + CellDependency.upsert_all(cell_deps_attrs, unique_by: %i[ckb_transaction_id contract_cell_id dep_type], update_only: :contract_analyzed) + end +end diff --git a/app/workers/contract_statistic_worker.rb b/app/workers/contract_statistic_worker.rb index 64d743f12..58e67ee31 100644 --- a/app/workers/contract_statistic_worker.rb +++ b/app/workers/contract_statistic_worker.rb @@ -4,42 +4,25 @@ class ContractStatisticWorker def perform h24_tx_ids = CkbTransaction.h24.pluck(:id) - pool_size = 10 - pool = Concurrent::FixedThreadPool.new(pool_size) + ActiveRecord::Base.connection.execute("SET statement_timeout = 0") + Contract.where(verified: true).find_each do |contract| + contract_cell_ids = CellDepsOutPoint.list_contract_cell_ids_by_contract([contract.id]) + ckb_transactions_count = CellDependency.where(contract_cell_id: contract_cell_ids).select(:ckb_transaction_id).distinct.count + h24_ckb_transactions_count = CellDependency.where(contract_cell_id: contract_cell_ids, ckb_transaction_id: h24_tx_ids).select(:ckb_transaction_id).distinct.count + referring_cells_count = Contract.referring_cells_query([contract]).count + total_deployed_cells_capacity = CellOutput.find(contract.deployed_cell_output_id).capacity + total_referring_cells_capacity = Contract.referring_cells_query([contract]).sum(:capacity) + addresses_count = Contract.referring_cells_query([contract]).distinct(:address_id).count - Contract.find_each do |contract| - ckb_address_ids = fetch_ckb_address_ids(contract, pool) contract.update( - ckb_transactions_count: contract.cell_dependencies.count, - h24_ckb_transactions_count: contract.cell_dependencies.where(ckb_transaction_id: h24_tx_ids).count, - deployed_cells_count: contract.deployed_cell_outputs&.live&.size, - referring_cells_count: contract.referring_cell_outputs.live.size, - total_deployed_cells_capacity: contract.deployed_cell_outputs&.live&.sum(:capacity), - total_referring_cells_capacity: contract.referring_cell_outputs.live.sum(:capacity), - addresses_count: ckb_address_ids.count, + ckb_transactions_count:, + h24_ckb_transactions_count:, + deployed_cells_count: 1, + referring_cells_count:, + total_deployed_cells_capacity:, + total_referring_cells_capacity:, + addresses_count:, ) end - - # 关闭线程池 - pool.shutdown - pool.wait_for_termination - end - - private - - def fetch_ckb_address_ids(contract, pool) - ckb_address_ids = Concurrent::Set.new - - futures = [] - - contract.referring_cell_outputs.live.find_in_batches(batch_size: 10_000) do |batch| - futures << Concurrent::Promises.future_on(pool) do - batch.each { |cell_output| ckb_address_ids.add(cell_output.address_id) } - end - end - - Concurrent::Promises.zip(*futures).value! - - ckb_address_ids end end diff --git a/app/workers/generate_cell_dependencies_worker.rb b/app/workers/generate_cell_dependencies_worker.rb index fdd191131..fb528d261 100644 --- a/app/workers/generate_cell_dependencies_worker.rb +++ b/app/workers/generate_cell_dependencies_worker.rb @@ -7,8 +7,7 @@ def perform(block_id) tx_cell_deps = build_cell_deps(block.number) block.ckb_transactions.each do |txs| - DeployedCell.create_initial_data_for_ckb_transaction(txs, tx_cell_deps[txs.tx_hash]) - ReferringCell.create_initial_data_for_ckb_transaction(txs) + CellDependency.parse_cell_dpes_from_ckb_transaction(txs, tx_cell_deps[txs.tx_hash]) end end diff --git a/app/workers/generate_udt_holder_allocation_worker.rb b/app/workers/generate_udt_holder_allocation_worker.rb index e81fbd530..5f60bf2b1 100644 --- a/app/workers/generate_udt_holder_allocation_worker.rb +++ b/app/workers/generate_udt_holder_allocation_worker.rb @@ -37,7 +37,7 @@ def update_contract_holder_allocation(udt) end allocation_data.each do |code_hash, count| - contract = Contract.find_by(code_hash:, role: ["LockScript", "lock_script"]) + contract = Contract.find_by(code_hash:, is_lock_script: true) next unless contract holder_allocation = UdtHolderAllocation.find_or_initialize_by(udt:, contract:) diff --git a/config/settings.testnet.yml b/config/settings.testnet.yml index 035fee2c1..3a6c5d389 100644 --- a/config/settings.testnet.yml +++ b/config/settings.testnet.yml @@ -21,12 +21,10 @@ nrc_721_factory_output_data_header: "0x24ff5a9ab8c38d195ce2b4ea75ca8987" nrc_721_token_output_data_header: "0x0ddeff3e8ee03cbf6a2c6920d05c381e" # spore nft code hash -spore_cluster1_code_hash: "0x7366a61534fa7c7e6225ecc0d828ea3b5366adec2b58206f2ee84995fe030075" # tag: v2 preview +spore_cluster1_code_hash: "0x0bbe768b519d8ea7b96d58f1182eb7e6ef96c541fbd9526975077ee09f049058" # tag: v2 preview spore_cluster2_code_hash: "0x598d793defef36e2eeba54a9b45130e4ca92822e1d193671f490950c3b856080" # tag: v1 latest -spore_cluster3_code_hash: "0x0bbe768b519d8ea7b96d58f1182eb7e6ef96c541fbd9526975077ee09f049058" # tag: 0.2.2-beta.2 -spore_cell1_code_hash: "0x5e063b4c0e7abeaa6a428df3b693521a3050934cf3b0ae97a800d1bc31449398" # tag: v2 preview +spore_cell1_code_hash: "0x685a60219309029d01310311dba953d67029170ca4848a4ff638e57002130a0d" # tag: v2 preview spore_cell2_code_hash: "0xbbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c133494" # tag: v1 latest -spore_cell3_code_hash: "0x685a60219309029d01310311dba953d67029170ca4848a4ff638e57002130a0d" # tag: 0.2.2-beta.2 #did cell did_cell_code_hash: "0x0b1f412fbae26853ff7d082d422c2bdd9e2ff94ee8aaec11240a5b34cc6e890f" diff --git a/db/migrate/20240823071323_add_unique_index_to_lock_script.rb b/db/migrate/20240823071323_add_unique_index_to_lock_script.rb index 08611666f..edf0901f5 100644 --- a/db/migrate/20240823071323_add_unique_index_to_lock_script.rb +++ b/db/migrate/20240823071323_add_unique_index_to_lock_script.rb @@ -1,13 +1,10 @@ class AddUniqueIndexToLockScript < ActiveRecord::Migration[7.0] - def up + def change # set 1 hour - execute "SET statement_timeout = 3600000" + execute "SET statement_timeout = 3600000;" remove_index :lock_scripts, :script_hash add_index :lock_scripts, :script_hash, unique: true - end - - def down - execute "RESET statement_timeout" + execute "RESET statement_timeout;" end end diff --git a/db/migrate/20240823071420_add_unique_index_to_type_script.rb b/db/migrate/20240823071420_add_unique_index_to_type_script.rb index e7650a460..bbe5e286a 100644 --- a/db/migrate/20240823071420_add_unique_index_to_type_script.rb +++ b/db/migrate/20240823071420_add_unique_index_to_type_script.rb @@ -1,13 +1,10 @@ class AddUniqueIndexToTypeScript < ActiveRecord::Migration[7.0] - def up + def change # set 1 hour - execute "SET statement_timeout = 3600000" + execute "SET statement_timeout = 3600000;" remove_index :type_scripts, :script_hash add_index :type_scripts, :script_hash, unique: true - end - - def down - execute "RESET statement_timeout" + execute "RESET statement_timeout;" end end diff --git a/db/migrate/20240904043807_change_ckb_transaction_confirmation_time.rb b/db/migrate/20240904043807_change_ckb_transaction_confirmation_time.rb index c6a8ad074..11eed3765 100644 --- a/db/migrate/20240904043807_change_ckb_transaction_confirmation_time.rb +++ b/db/migrate/20240904043807_change_ckb_transaction_confirmation_time.rb @@ -1,6 +1,7 @@ class ChangeCkbTransactionConfirmationTime < ActiveRecord::Migration[7.0] def change - ActiveRecord::Base.connection.execute("SET statement_timeout = 0") + execute("SET statement_timeout = 0;") change_column :ckb_transactions, :confirmation_time, :bigint + execute "RESET statement_timeout;" end end diff --git a/db/migrate/20241105070340_create_cell_deps_out_point.rb b/db/migrate/20241105070340_create_cell_deps_out_point.rb new file mode 100644 index 000000000..8712e25ab --- /dev/null +++ b/db/migrate/20241105070340_create_cell_deps_out_point.rb @@ -0,0 +1,14 @@ +class CreateCellDepsOutPoint < ActiveRecord::Migration[7.0] + def change + create_table :cell_deps_out_points do |t| + t.binary :tx_hash + t.integer :cell_index + t.bigint :deployed_cell_output_id + t.bigint :contract_cell_id + + t.timestamps + end + + add_index :cell_deps_out_points, %i[contract_cell_id deployed_cell_output_id], name: "index_cell_deps_out_points_on_contract_cell_id_deployed_cell_id", unique: true + end +end diff --git a/db/migrate/20241105070619_remove_implicit_column_from_cell_dependency.rb b/db/migrate/20241105070619_remove_implicit_column_from_cell_dependency.rb new file mode 100644 index 000000000..a4950e199 --- /dev/null +++ b/db/migrate/20241105070619_remove_implicit_column_from_cell_dependency.rb @@ -0,0 +1,8 @@ +class RemoveImplicitColumnFromCellDependency < ActiveRecord::Migration[7.0] + def change + add_column :cell_dependencies, :block_number, :bigint + add_column :cell_dependencies, :tx_index, :int + + add_index :cell_dependencies, %i[block_number tx_index] + end +end diff --git a/db/migrate/20241106062022_add_type_hash_data_hash_to_contract.rb b/db/migrate/20241106062022_add_type_hash_data_hash_to_contract.rb new file mode 100644 index 000000000..99cf88ba2 --- /dev/null +++ b/db/migrate/20241106062022_add_type_hash_data_hash_to_contract.rb @@ -0,0 +1,9 @@ +class AddTypeHashDataHashToContract < ActiveRecord::Migration[7.0] + def change + add_column :contracts, :type_hash, :binary + add_column :contracts, :data_hash, :binary + add_column :contracts, :deployed_cell_output_id, :bigint + add_column :contracts, :is_type_script, :boolean + add_column :contracts, :is_lock_script, :boolean + end +end diff --git a/db/migrate/20241114074433_add_unique_index_to_contracts.rb b/db/migrate/20241114074433_add_unique_index_to_contracts.rb new file mode 100644 index 000000000..06f3f2d82 --- /dev/null +++ b/db/migrate/20241114074433_add_unique_index_to_contracts.rb @@ -0,0 +1,5 @@ +class AddUniqueIndexToContracts < ActiveRecord::Migration[7.0] + def change + add_index :contracts, :deployed_cell_output_id, unique: true + end +end diff --git a/db/migrate/20241119014652_reset_cell_dependency_unique_index.rb b/db/migrate/20241119014652_reset_cell_dependency_unique_index.rb new file mode 100644 index 000000000..feee1b01f --- /dev/null +++ b/db/migrate/20241119014652_reset_cell_dependency_unique_index.rb @@ -0,0 +1,9 @@ +class ResetCellDependencyUniqueIndex < ActiveRecord::Migration[7.0] + def change + execute "SET statement_timeout = 3600000" + remove_index :cell_dependencies, column: %i[ckb_transaction_id contract_cell_id] + + add_index :cell_dependencies, %i[ckb_transaction_id contract_cell_id dep_type], name: "index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type", unique: true + execute "RESET statement_timeout;" + end +end diff --git a/db/migrate/20241121073245_add_sorted_index_to_cell_dependencies.rb b/db/migrate/20241121073245_add_sorted_index_to_cell_dependencies.rb new file mode 100644 index 000000000..66529c9a5 --- /dev/null +++ b/db/migrate/20241121073245_add_sorted_index_to_cell_dependencies.rb @@ -0,0 +1,11 @@ +class AddSortedIndexToCellDependencies < ActiveRecord::Migration[7.0] + def change + execute("SET statement_timeout = 0;") + + remove_index :cell_dependencies, column: :contract_cell_id + add_index :cell_dependencies, %i[contract_cell_id block_number tx_index], + order: { block_number: :desc, tx_index: :desc }, + name: "index_on_cell_dependencies_contract_cell_block_tx" + execute "RESET statement_timeout;" + end +end diff --git a/db/migrate/20241125100650_add_contract_analyzed_to_cell_dependency.rb b/db/migrate/20241125100650_add_contract_analyzed_to_cell_dependency.rb new file mode 100644 index 000000000..12b885836 --- /dev/null +++ b/db/migrate/20241125100650_add_contract_analyzed_to_cell_dependency.rb @@ -0,0 +1,5 @@ +class AddContractAnalyzedToCellDependency < ActiveRecord::Migration[7.0] + def change + add_column :cell_dependencies, :contract_analyzed, :boolean, default: false + end +end diff --git a/db/migrate/20241129000339_add_contract_analyzed_index_to_cell_dependency.rb b/db/migrate/20241129000339_add_contract_analyzed_index_to_cell_dependency.rb new file mode 100644 index 000000000..b9a908d28 --- /dev/null +++ b/db/migrate/20241129000339_add_contract_analyzed_index_to_cell_dependency.rb @@ -0,0 +1,7 @@ +class AddContractAnalyzedIndexToCellDependency < ActiveRecord::Migration[7.0] + def change + execute("SET statement_timeout = 0;") + add_index :cell_dependencies, :contract_analyzed + execute "RESET statement_timeout;" + end +end diff --git a/db/structure.sql b/db/structure.sql index b37f2e718..bbe7b508d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1035,12 +1035,15 @@ ALTER SEQUENCE public.cell_data_cell_output_id_seq OWNED BY public.cell_data.cel CREATE TABLE public.cell_dependencies ( id bigint NOT NULL, - 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, + contract_analyzed boolean DEFAULT false ); @@ -1063,6 +1066,40 @@ CREATE SEQUENCE public.cell_dependencies_id_seq ALTER SEQUENCE public.cell_dependencies_id_seq OWNED BY public.cell_dependencies.id; +-- +-- Name: cell_deps_out_points; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.cell_deps_out_points ( + id bigint NOT NULL, + tx_hash bytea, + cell_index integer, + deployed_cell_output_id bigint, + contract_cell_id bigint, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: cell_deps_out_points_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.cell_deps_out_points_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: cell_deps_out_points_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.cell_deps_out_points_id_seq OWNED BY public.cell_deps_out_points.id; + + -- -- Name: cell_inputs; Type: TABLE; Schema: public; Owner: - -- @@ -1445,7 +1482,12 @@ CREATE TABLE public.contracts ( total_deployed_cells_capacity numeric(30,0) DEFAULT 0.0, total_referring_cells_capacity numeric(30,0) DEFAULT 0.0, addresses_count integer, - h24_ckb_transactions_count integer + h24_ckb_transactions_count integer, + type_hash bytea, + data_hash bytea, + deployed_cell_output_id bigint, + is_type_script boolean, + is_lock_script boolean ); @@ -2996,6 +3038,13 @@ ALTER TABLE ONLY public.cell_data ALTER COLUMN cell_output_id SET DEFAULT nextva ALTER TABLE ONLY public.cell_dependencies ALTER COLUMN id SET DEFAULT nextval('public.cell_dependencies_id_seq'::regclass); +-- +-- Name: cell_deps_out_points id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cell_deps_out_points ALTER COLUMN id SET DEFAULT nextval('public.cell_deps_out_points_id_seq'::regclass); + + -- -- Name: cell_inputs id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3414,6 +3463,14 @@ ALTER TABLE ONLY public.cell_dependencies ADD CONSTRAINT cell_dependencies_pkey PRIMARY KEY (id); +-- +-- Name: cell_deps_out_points cell_deps_out_points_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cell_deps_out_points + ADD CONSTRAINT cell_deps_out_points_pkey PRIMARY KEY (id); + + -- -- Name: cell_inputs cell_inputs_pkey_new; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -3882,13 +3939,6 @@ CREATE UNIQUE INDEX block_tx_alt_pk ON public.block_transactions USING btree (bl CREATE UNIQUE INDEX block_tx_index ON public.block_transactions USING btree (block_id, tx_index); --- --- Name: cell_deps_tx_cell_idx; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX cell_deps_tx_cell_idx ON public.cell_dependencies USING btree (ckb_transaction_id, contract_cell_id); - - -- -- Name: index_cell_outputs_on_address_id; Type: INDEX; Schema: public; Owner: - -- @@ -4611,24 +4661,31 @@ CREATE INDEX index_blocks_on_timestamp ON public.blocks USING btree ("timestamp" -- --- Name: index_cell_dependencies_on_contract_cell_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cell_dependencies_on_block_number_and_tx_index; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_cell_dependencies_on_block_number_and_tx_index ON public.cell_dependencies USING btree (block_number, tx_index); + + +-- +-- Name: index_cell_dependencies_on_contract_analyzed; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cell_dependencies_on_contract_cell_id ON public.cell_dependencies USING btree (contract_cell_id); +CREATE INDEX index_cell_dependencies_on_contract_analyzed ON public.cell_dependencies USING btree (contract_analyzed); -- --- Name: index_cell_dependencies_on_contract_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cell_dependencies_on_contract_id ON public.cell_dependencies USING btree (contract_id); +CREATE UNIQUE INDEX index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type ON public.cell_dependencies USING btree (ckb_transaction_id, contract_cell_id, dep_type); -- --- Name: index_cell_dependencies_on_script_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cell_deps_out_points_on_contract_cell_id_deployed_cell_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cell_dependencies_on_script_id ON public.cell_dependencies USING btree (script_id); +CREATE UNIQUE INDEX index_cell_deps_out_points_on_contract_cell_id_deployed_cell_id ON public.cell_deps_out_points USING btree (contract_cell_id, deployed_cell_output_id); -- @@ -4645,6 +4702,13 @@ CREATE UNIQUE INDEX index_cell_inputs_on_ckb_transaction_id_and_index ON public. CREATE INDEX index_contracts_on_code_hash ON public.contracts USING btree (code_hash); +-- +-- Name: index_contracts_on_deployed_cell_output_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_contracts_on_deployed_cell_output_id ON public.contracts USING btree (deployed_cell_output_id); + + -- -- Name: index_contracts_on_deprecated; Type: INDEX; Schema: public; Owner: - -- @@ -4827,6 +4891,13 @@ CREATE UNIQUE INDEX index_nrc_factory_cells_on_code_hash_and_hash_type_and_args CREATE UNIQUE INDEX index_omiga_inscription_infos_on_udt_hash ON public.omiga_inscription_infos USING btree (udt_hash); +-- +-- Name: index_on_cell_dependencies_contract_cell_block_tx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_on_cell_dependencies_contract_cell_block_tx ON public.cell_dependencies USING btree (contract_cell_id, block_number DESC, tx_index DESC); + + -- -- Name: index_portfolios_on_user_id_and_address_id; Type: INDEX; Schema: public; Owner: - -- @@ -5947,5 +6018,14 @@ INSERT INTO "schema_migrations" (version) VALUES ('20240823071420'), ('20240902025657'), ('20240904043807'), +('20241105070340'), +('20241105070619'), +('20241106062022'), +('20241114074433'), +('20241119014652'), +('20241121073245'), +('20241125100650'), +('20241129000339'), ('20241202072604'); + diff --git a/lib/scheduler.rb b/lib/scheduler.rb index 4e47cd783..364ab7997 100644 --- a/lib/scheduler.rb +++ b/lib/scheduler.rb @@ -128,4 +128,8 @@ def call_worker(clz) call_worker GenerateUdtHolderAllocationWorker end +s.every "5s", overlap: false do + call_worker AnalyzeContractFromCellDependencyWorker +end + s.join diff --git a/lib/tasks/migration/fill_cell_dependency_block_number_and_tx_index.rake b/lib/tasks/migration/fill_cell_dependency_block_number_and_tx_index.rake new file mode 100644 index 000000000..60dc3512f --- /dev/null +++ b/lib/tasks/migration/fill_cell_dependency_block_number_and_tx_index.rake @@ -0,0 +1,46 @@ +namespace :migration do + desc "Usage: RAILS_ENV=production bundle exec rake migration:fill_cell_dependency_block_number_and_tx_index[0,10000]" + task :fill_cell_dependency_block_number_and_tx_index, %i[start_block end_block] => :environment do |_, args| + $retry_ids = Set.new + @api = CKB::API.new(host: ENV["CKB_NODE_URL"], + timeout_config: { + open_timeout: 1, read_timeout: 3, + write_timeout: 1 + }) + (args[:start_block].to_i..args[:end_block].to_i).to_a.each_slice(100).to_a.each do |range| + compare_cell_dependency(range, 0) + end; nil + + puts "retry IDS:" + puts $retry_ids.join(",") + puts "done" + end + + def compare_cell_dependency(range, retry_count) + request_body = + range.map do |number| + ["get_block_by_number", number] + end + response = @api.batch_request(*request_body) + response.each do |r| + attrs = [] + r[:transactions].each do |tx| + if tx[:cell_deps].length > 0 + local_tx = CkbTransaction.find_by(tx_hash: tx[:hash]) + tx[:cell_deps].map do |cell_dep| + co = CellOutput.find_by(tx_hash: cell_dep[:out_point][:tx_hash], cell_index: (cell_dep[:out_point][:index]).to_i(16)) + attrs << { block_number: local_tx.block_number, tx_index: local_tx.tx_index, contract_cell_id: co.id, dep_type: cell_dep[:dep_type], ckb_transaction_id: local_tx.id } + end + end + end; nil + CellDependency.upsert_all(attrs, unique_by: %i[ckb_transaction_id contract_cell_id dep_type], update_only: %i[block_number tx_index]) if attrs.present? + end; nil + rescue StandardError => _e + retry_count += 1 + if retry_count > 2 + $retry_ids << range.first + else + compare_cell_dependency(range, retry_count) + end + end +end diff --git a/lib/tasks/migration/fill_cell_deps_out_point.rake b/lib/tasks/migration/fill_cell_deps_out_point.rake new file mode 100644 index 000000000..21c217baa --- /dev/null +++ b/lib/tasks/migration/fill_cell_deps_out_point.rake @@ -0,0 +1,37 @@ +namespace :migration do + desc "Usage: RAILS_ENV=production bundle exec rake migration:fill_cell_deps_out_point" + task fill_cell_deps_out_point: :environment do + ActiveRecord::Base.connection.execute("SET statement_timeout = 0") + error_ids = [] + CellDependency.left_joins(:cell_deps_out_point).where(cell_deps_out_point: { id: nil }).select(:contract_cell_id).distinct.in_batches do |batch| + batch.each do |missed_cell_dep| + CellDependency.where(contract_cell_id: missed_cell_dep.contract_cell_id).select(:dep_type).distinct.each do |cell_dep| + if cell_dep.dep_type == "code" + output = CellOutput.find(missed_cell_dep.contract_cell_id) + CellDepsOutPoint.upsert_all([tx_hash: output.tx_hash, cell_index: output.cell_index, deployed_cell_output_id: output.id, contract_cell_id: output.id]) + else + cell_deps_out_points_attrs = [] + mid_cell = CellOutput.find(missed_cell_dep.contract_cell_id) + binary_data = mid_cell.binary_data + out_points_count = binary_data[0, 4].unpack("L<") + 0.upto(out_points_count[0] - 1) do |i| + part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<") + tx_hash = "0x#{part_tx_hash}" + 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, + } + end + CellDepsOutPoint.upsert_all(cell_deps_out_points_attrs) + end + rescue StandardError => _e + error_ids << missed_cell_dep.contract_cell_id + end + end + end + puts "done" + end +end diff --git a/lib/tasks/migration/fill_contracts_info.rake b/lib/tasks/migration/fill_contracts_info.rake new file mode 100644 index 000000000..bbc6933d0 --- /dev/null +++ b/lib/tasks/migration/fill_contracts_info.rake @@ -0,0 +1,483 @@ +namespace :migration do + desc "Usage: RAILS_ENV=production bundle exec rake migration:fill_contracts_info" + task fill_contracts_info: :environment do + hashes = + if ENV["CKB_NET_MODE"] == "mainnet" + [ + { code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", hash_type: "type", + name: "SECP256K1/blake160", + tx_hashes: ["0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c-0"], + dep_type: "dep_group", + description: "SECP256K1/blake160 is the default lock script to verify CKB transaction signature." }, + { code_hash: "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8", hash_type: "type", + name: "SECP256K1/multisig", + tx_hashes: ["0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c-1"], + dep_type: "dep_group", + description: "SECP256K1/multisig is a script which allows a group of users to sign a single transaction." }, + { code_hash: "0x0fb343953ee78c9986b091defb6252154e0bb51044fd2879fde5b27314506111", hash_type: "type", + name: "Anyone-Can-Pay Lock", + tx_hashes: ["0xa05f28c9b867f8c5682039c10d8e864cf661685252aa74a008d255c33813bb81-0"], + dep_type: "dep_group", + description: "anyone_can_pay allows a recipient to provide cell capacity in asset transfer.", + deprecated: true }, + { code_hash: "0xd369597ff47f29fbc0d47d2e3775370d1250b85140c670e4718af712983a2354", hash_type: "type", + name: "Anyone-Can-Pay Lock", + tx_hashes: ["0x4153a2014952d7cac45f285ce9a7c5c0c0e1b21f2d378b82ac1433cb11c25c4d-0"], + dep_type: "dep_group", + description: "anyone_can_pay allows a recipient to provide cell capacity in asset transfer." }, + { code_hash: "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e", hash_type: "type", + name: "Nervos DAO", + tx_hashes: ["0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c-2"], + dep_type: "code", + description: "Nervos DAO is a smart contract with which users can interact the same way as any smart contract on CKB." }, + { code_hash: "0x5e7a36a77e68eecc013dfa2fe6a23f3b6c344b04005808694ae6dd45eea4cfd5", hash_type: "type", + name: "Simple UDT", + tx_hashes: ["0xc7813f6a415144643970c2e88e0bb6ca6a8edc5dd7c1022746f628284a9936d5-0"], + dep_type: "code", + description: "Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB." }, + { code_hash: "0xbf43c3602455798c1a61a596e0d95278864c552fafe231c063b3fabf97a8febc", hash_type: "type", + name: "PW Lock", + dep_type: "code", + tx_hashes: ["0x1d60cb8f4666e039f418ea94730b1a8c5aa0bf2f7781474406387462924d15d4-0"], + description: "Forked from CKB's system scripts, and currently supports signature generated by personalSign and signTypedData from ethereum wallets." }, + { code_hash: "0x614d40a86e1b29a8f4d8d93b9f3b390bf740803fa19a69f1c95716e029ea09b3", hash_type: "type", + name: "Unipass V2", + tx_hashes: ["0x1a04142a2a745fb3b7e0e9b61241676c1c94ad8cdacb36f223661130a23fb007-0"], dep_type: "code", + description: "UniPass Wallet is a smart contract wallet solution that supports on-chain Email social recovery." }, + { code_hash: "0xd01f5152c267b7f33b9795140c2467742e8424e49ebe2331caec197f7281b60a", hash_type: "type", + name: "Unipass V3", + tx_hashes: ["0x86a5e91ad93475caf30a3d3b0258786dd463984f71e8471abc5574f206f6207a-0"], dep_type: "code", + description: "UniPass Wallet is a smart contract wallet solution that supports on-chain Email social recovery." }, + { code_hash: "0xe4d4ecc6e5f9a059bf2f7a82cca292083aebc0c421566a52484fe2ec51a9fb0c", hash_type: "type", + name: "CHEQUE", + tx_hashes: ["0x04632cc459459cf5c9d384b43dee3e36f542a464bdd4127be7d6618ac6f8d268-0"], + dep_type: "code", + description: "" }, + { code_hash: "0x1122a4fb54697cf2e6e3a96c9d80fd398a936559b90954c6e88eb7ba0cf652df", hash_type: "type", + name: "CoTA", + tx_hashes: [ + "0x875db3381ebe7a730676c110e1c0d78ae1bdd0c11beacb7db4db08e368c2cd95-0", + "0xae2d5838730fc096e68fe839aea50d294493e10054513c10ca35e77e82e9243b-0", + ], + dep_type: "dep_group", + description: "A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs." }, + { code_hash: "0x90ca618be6c15f5857d3cbd09f9f24ca6770af047ba9ee70989ec3b229419ac7", hash_type: "type", + name: "CoTA Registry", + tx_hashes: [ + "0x875db3381ebe7a730676c110e1c0d78ae1bdd0c11beacb7db4db08e368c2cd95-0", + "0xae2d5838730fc096e68fe839aea50d294493e10054513c10ca35e77e82e9243b-0", + ], + dep_type: "dep_group", + description: "A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs." }, + { code_hash: "0x081dbffa88dab54ba426d231ca64eb760cea2fe9e16761a1da400da1b2cbe128", hash_type: "type", + name: "Flash Signer", + tx_hashes: ["0x0f0c22372a05f3c5f47acb066c65f9bae86bdce043762310e50309cc5a77abd4-0"], + dep_type: "dep_group", + description: "" }, + + { code_hash: "0x000f87062a2fe9bb4a6cc475212ea11014b84deb32e0375ee51e6ec4a553e009", hash_type: "type", + name: "Godwoken Custodian Lock", + tx_hashes: ["0x71b55e3641fdc8d00d9943a93b2c6e6ab42f7e57909009c2a1ad5c234956cdc5-0"], + dep_type: "code", + description: "Rollup uses the custodian lock to hold the deposited assets." }, + { code_hash: "0xff602581f07667eef54232cce850cbca2c418b3418611c132fca849d1edcd775", hash_type: "type", + name: "Godwoken Deposit Lock", + tx_hashes: ["0x61e576a7e5d2398ecc5b1a969d1af0142c87db0996c2f6fce41bf28f68d805b2-0"], + dep_type: "code", + description: "A layer1 user can join the Rollup by creating a deposit cell." }, + { code_hash: "0x3714af858b8b82b2bb8f13d51f3cffede2dd8d352a6938334bb79e6b845e3658", hash_type: "type", + name: "Godwoken Withdrawal Lock", + tx_hashes: ["0xe6389b5cf63eec1e2592e930414bc43f92508e529bdd5f5a07fa1dd140f4f20a-0"], + dep_type: "code", + description: "Withdrawal cells are generated in the RollupSubmitBlock action according to the block.withdrawals field." }, + { code_hash: "0x628b5f956b46ae27b50819a9ebab79ce5f957e6899ba0c75b8e142de2ed0dcd2", hash_type: "type", + name: "Godwoken Challenge Lock", + tx_hashes: ["0x8eca99207a462a9005bd91d04e24911627769096220f867d1cc0a32e75a287a6-0"], + dep_type: "code", + description: "When a Godwoken node found that an invalid state exists in the Rollup, the node can send the RollupEnterChallenge action to the Rollup cell and generate a challenging cell." }, + { code_hash: "0xb619184ab9142c51b0ee75f4e24bcec3d077eefe513115bad68836d06738fd2c", hash_type: "type", + name: "Godwoken Stake Lock", + tx_hashes: ["0x2e46a10a67987594d4eaee2d5f9ac96ce651f7bfb44e82c286a12a1950ad4f29-0"], + dep_type: "code", + description: "A block producer is required to provide a stake cell to perform the RollupSubmitBlock action." }, + { code_hash: "0xfef1d086d9f74d143c60bf03bd04bab29200dbf484c801c72774f2056d4c6718", hash_type: "type", + name: "Godwoken State Validator", + tx_hashes: ["0x9f8e73e096f1583696760281004d71dc0cebd3c9aa6fb584949facde6e543e67-0"], + dep_type: "code", + description: "State validator is the major script to verify the on-chain Rollup cell. Rollup cell is an identity cell on CKB, it stores the structure GlobalState which represents the layer-2 state." }, + { code_hash: "0x096df264f38fff07f3acd318995abc2c71ae0e504036fe32bc38d5b6037364d4", hash_type: "type", + name: "Godwoken Eth Account Lock", + tx_hashes: ["0xf0cfb02fb435bf2f061cbf33b1b024a4944b3f4a95968a9d997d95dd2f76a7f9-0"], + dep_type: "code", + description: "A layer-2 lock script, ETH account lock is a script that verifies the layer-2 account signature." }, + { code_hash: "0xa4398768d87bd17aea1361edc3accd6a0117774dc4ebc813bfa173e8ac0d086d", hash_type: "type", + name: "OMNI Lock V1", + tx_hashes: ["0x625696834db4320214a8af09de74fd51fc8a83be69d920243f8ccd219071473b-0"], + dep_type: "code", + description: "Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future." }, + { code_hash: "0x9b819793a64463aed77c615d6cb226eea5487ccfc0783043a587254cda2b6f26", hash_type: "type", + name: "OMNI Lock V2", + tx_hashes: [ + "0xc76edf469816aa22f416503c38d0b533d2a018e253e379f134c3985b3472c842-0", + "0xdfdb40f5d229536915f2d5403c66047e162e25dedd70a79ef5164356e1facdc8-0", + ], + dep_type: "code", + description: "Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future." }, + { code_hash: "0xd00c84f0ec8fd441c38bc3f87a371f547190f2fcff88e642bc5bf54b9e318323", hash_type: "type", + name: "JoyID", + dep_type: "dep_group", + description: "An universal Account Protocol for Web3 Mass-adoption.", + tx_hashes: ["0xf05188e5f3a6767fc4687faf45ba5f1a6e25d3ada6129dae8722cb282f262493-0"] }, + { code_hash: "0x50bd8d6680b8b9cf98b73f3c08faf8b2a21914311954118ad6609be6e78a1b95", hash_type: "data1", + name: "xUDT", + description: "Extensible UDT that derived from sUDT's programmability to support a wider range of scenarios", + dep_type: "code", + tx_hashes: ["0xc07844ce21b38e4b071dd0e1ee3b0e27afd8d7532491327f39b786343f558ab7-0"] }, + { code_hash: "0xbbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c133494", hash_type: "data1", + name: "Spore", + dep_type: "code", + tx_hashes: ["0x96b198fb5ddbd1eed57ed667068f1f1e55d07907b4c0dbd38675a69ea1b69824-0"], + description: "Spore Protocol infuses digital assets with enduring value backed by tokenomics, redeemable at any time. Ensures true on-chain ownership, privacy, creative freedom and frictionless interaction." }, + { code_hash: "0x7366a61534fa7c7e6225ecc0d828ea3b5366adec2b58206f2ee84995fe030075", hash_type: "data1", + name: "Spore Cluster", + dep_type: "code", + tx_hashes: ["0xe464b7fb9311c5e2820e61c99afc615d6b98bdefbe318c34868c010cbd0dc938-0"], + description: "" }, + { code_hash: "0x9f3aeaf2fc439549cbc870c653374943af96a0658bd6b51be8d8983183e6f52f", hash_type: "type", + name: "Force Bridge", + dep_type: "code", + tx_hashes: ["0xaa8ab7e97ed6a268be5d7e26d63d115fa77230e51ae437fc532988dd0c3ce10a-1"], + description: "" }, + { code_hash: "0xbc6c568a1a0d0a09f6844dc9d74ddb4343c32143ff25f727c59edf4fb72d6936", hash_type: "type", + name: "RGB++", + dep_type: "code", + description: "RGB++ Lock", + tx_hashes: ["0x04c5c3e69f1aa6ee27fb9de3d15a81704e387ab3b453965adbe0b6ca343c6f41-0"] }, + { code_hash: "0x2c8c11c985da60b0a330c61a85507416d6382c130ba67f0c47ab071e00aec628", hash_type: "data1", + name: "Unique Cell", + dep_type: "code", + tx_hashes: ["0x67524c01c0cb5492e499c7c7e406f2f9d823e162d6b0cf432eacde0c9808c2ad-0"], + description: "A unique cell can be created on the Nervos CKB through TypeID which makes sure the unique cell cannot be updated or destroyed." }, + { code_hash: "0x70d64497a075bd651e98ac030455ea200637ee325a12ad08aff03f1a117e5a62", hash_type: "type", + name: "Btc Time Lock", + dep_type: "code", + tx_hashes: ["0x6257bf4297ee75fcebe2654d8c5f8d93bc9fc1b3dc62b8cef54ffe166162e996-0"], + description: "A lock require n confirmations of Bitcoin transaction to unlock the cell." }, + { code_hash: "0xcfba73b58b6f30e70caed8a999748781b164ef9a1e218424a6fb55ebf641cb33", hash_type: "type", + tx_hashes: ["0xeda235b56aa422c497b9b9bcfde7af289376e7fe12449ade99176609005994ba-0"], + name: "DID", + dep_type: "code", + description: "" }, + { code_hash: "0x641a89ad2f77721b803cd50d01351c1f308444072d5fa20088567196c0574c68", hash_type: "type", + name: "Nostr", + dep_type: "code", + tx_hashes: ["0x1911208b136957d5f7c1708a8835edfe8ae1d02700d5cb2c3a6aacf4d5906306-0"], + description: "The Nostr lock script is designed for interoperability with Nostr." }, + { code_hash: "0x8290467a512e5b9a6b816469b0edabba1f4ac474e28ffdd604c2a7c76446bbaf", hash_type: "data1", + name: "Single Use Lock", + dep_type: "code", + tx_hashes: ["0x10d63a996157d32c01078058000052674ca58d15f921bec7f1dcdac2160eb66b-4"], + description: "A lock script that can only be used once." }, + { code_hash: "0x2a8100ab5990fa055ab1b50891702e1e895c7bd1df6322cd725c1a6115873bd3", hash_type: "data1", + name: "iCKB Logic", + dep_type: "dep_group", + tx_hashes: ["0x621a6f38de3b9f453016780edac3b26bfcbfa3e2ecb47c2da275471a5d3ed165-0"], + description: "iCKB Logic tokenizes NervosDAO deposits into the iCKB xUDT token." }, + { code_hash: "0xacc79e07d107831feef4c70c9e683dac5644d5993b9cb106dca6e74baa381bd0", hash_type: "data1", + name: "WR Owned-Owner", + dep_type: "dep_group", + tx_hashes: ["0x621a6f38de3b9f453016780edac3b26bfcbfa3e2ecb47c2da275471a5d3ed165-0"], + description: + "WR Owned-Owner enable to create Withdrawals Request from NervosDAO deposits locked with zero length args locks, developed as part of iCKB." }, + { code_hash: "0x49dfb6afee5cc8ac4225aeea8cb8928b150caf3cd92fea33750683c74b13254a", hash_type: "data1", + name: "UDT Limit Orderr", + dep_type: "dep_group", + tx_hashes: ["0x621a6f38de3b9f453016780edac3b26bfcbfa3e2ecb47c2da275471a5d3ed165-0"], + description: "UDT Limit Order is a general purpose UDT based Limit Order, developed as part of iCKB." }, + ] + else + [ + { code_hash: "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", hash_type: "type", + name: "SECP256K1/blake160", + dep_type: "dep_group", + tx_hashes: ["0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37-0"], + description: "SECP256K1/blake160 is the default lock script to verify CKB transaction signature.", + rfc: "https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1blake160", + code: "https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/secp256k1_blake160_sighash_all.c" }, + { code_hash: "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8", hash_type: "type", + name: "SECP256K1/multisig", + dep_type: "dep_group", + tx_hashes: ["0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37-1"], + description: "SECP256K1/multisig is a script which allows a group of users to sign a single transaction.", + rfc: "https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1multisig", + code: "https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/secp256k1_blake160_multisig_all.c" }, + { code_hash: "0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b", hash_type: "type", name: "Anyone-Can-Pay Lock", + dep_type: "dep_group", + description: "anyone_can_pay allows a recipient to provide cell capacity in asset transfer.", + tx_hashes: ["0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c-0"], + rfc: "https://github.com/nervosnetwork/rfcs/blob/30980b378fdaccc6e9d21a1c6b53363364fb4abc/rfcs/0026-anyone-can-pay/0026-anyone-can-pay.md", + code: "https://github.com/nervosnetwork/ckb-production-scripts/tree/deac6801a95596d74e2da8f2f1a6727309d36100", + deprecated: true }, + { code_hash: "0x3419a1c09eb2567f6552ee7a8ecffd64155cffe0f1796e6e61ec088d740c1356", hash_type: "type", name: "Anyone-Can-Pay Lock", + description: "anyone_can_pay allows a recipient to provide cell capacity in asset transfer.", + tx_hashes: ["0xec26b0f85ed839ece5f11c4c4e837ec359f5adc4420410f6453b1f6b60fb96a6-0"], + rfc: "https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0026-anyone-can-pay/0026-anyone-can-pay.md", + code: "https://github.com/nervosnetwork/ckb-production-scripts/blob/e570c11aff3eca12a47237c21598429088c610d5/c/anyone_can_pay.c" }, + { code_hash: "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e", hash_type: "type", + name: "Nervos DAO", + dep_type: "code", + tx_hashes: ["0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f-2"], + description: "Nervos DAO is a smart contract with which users can interact the same way as any smart contract on CKB.", rfc: "https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md", + code: "https://github.com/nervosnetwork/ckb-system-scripts/blob/master/c/dao.c" }, + { code_hash: "0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4", hash_type: "type", name: "Simple UDT", + description: "Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB.", + tx_hashes: ["0xe12877ebd2c3c364dc46c5c992bcfaf4fee33fa13eebdf82c591fc9825aab769-0"], + dep_type: "code", + rfc: "https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0025-simple-udt/0025-simple-udt.md", + code: "https://github.com/nervosnetwork/ckb-production-scripts/blob/e570c11aff3eca12a47237c21598429088c610d5/c/simple_udt.c" }, + { code_hash: "0x58c5f491aba6d61678b7cf7edf4910b1f5e00ec0cde2f42e0abb4fd9aff25a63", hash_type: "type", name: "PW Lock", + description: "Forked from CKB's system scripts, and currently supports signature generated by personalSign and signTypedData from ethereum wallets.", + dep_type: "code", + tx_hashes: ["0x57a62003daeab9d54aa29b944fc3b451213a5ebdf2e232216a3cfed0dde61b38-0"] }, + { code_hash: "0x124a60cd799e1fbca664196de46b3f7f0ecb7138133dcaea4893c51df5b02be6", hash_type: "type", + name: "Unipass V2", + dep_type: "code", + description: "UniPass Wallet is a smart contract wallet solution that supports on-chain Email social recovery.", + tx_hashes: ["0x3d41e1c543f0fddcbb17157d15a2845d7c5fb0363561cd8f50ecd0e118b34f84-0"] }, + { code_hash: "0x3e1eb7ed4809b2d60650be96a40abfbdafb3fb942b7b37ec7709e64e2cd0a783", hash_type: "type", name: "Unipass V3", + description: "UniPass Wallet is a smart contract wallet solution that supports on-chain Email social recovery.", + dep_type: "code", + tx_hashes: ["0x8b98ede6bf7b5baba767b1d2d46a13749fc810375b14152abbc259a7fc98e46d-0"] }, + { code_hash: "0x60d5f39efce409c587cb9ea359cefdead650ca128f0bd9cb3855348f98c70d5b", hash_type: "type", name: "CHEQUE", + dep_type: "dep_group", + description: "", + tx_hashes: ["0x7f96858be0a9d584b4a9ea190e0420835156a6010a5fde15ffcdc9d9c721ccab-0"] }, + { code_hash: "0xb59879b6ea6fff985223117fa499ce84f8cfb028c4ffdfdf5d3ec19e905a11ed", hash_type: "type", + name: "M-NFT Issuer", + dep_type: "code", + tx_hashes: [ + "0x744d2c4c4e6fabe66cfb08cb818532c50fffc682a7614746328c5d691a811c06-0", + "0xbd262c87a84c08ea3bc141700cf55c1a285009de0e22c247a8d9597b4fc491e6-0", + "0x194a0f84de41d006a07ece07c96a8130100818599fcf0b2ecf49e512b873ed6e-0", + "0x3ecf42927509645dec38667d557dd9ba20d0d07267d769983495c1b6b9c70cc4-0", + "0xf11ccb6079c1a4b3d86abe2c574c5db8d2fd3505fdc1d5970b69b31864a4bd1c-0", + ], + description: "" }, + { code_hash: "0x095b8c0b4e51a45f953acd1fcd1e39489f2675b4bc94e7af27bb38958790e3fc", hash_type: "type", + name: "M-NFT Class", + dep_type: "code", + tx_hashes: [ + "0x4f27e40b302bcb3bf0af3deae460f46076de2b4db30c0212b14b341c20fcb330-0", + "0xbd262c87a84c08ea3bc141700cf55c1a285009de0e22c247a8d9597b4fc491e6-1", + "0x194a0f84de41d006a07ece07c96a8130100818599fcf0b2ecf49e512b873ed6e-1", + "0x3ecf42927509645dec38667d557dd9ba20d0d07267d769983495c1b6b9c70cc4-1", + "0xf11ccb6079c1a4b3d86abe2c574c5db8d2fd3505fdc1d5970b69b31864a4bd1c-1", + ] }, + { code_hash: "0xb1837b5ad01a88558731953062d1f5cb547adf89ece01e8934a9f0aeed2d959f", hash_type: "type", + name: "M-NFT", + dep_type: "code", + tx_hashes: [ + "0x7f9e3c1a2fc90411eb90fc2363101f6bd7b33875c3535117db5e52cd8a78b313-0", + "0xbd262c87a84c08ea3bc141700cf55c1a285009de0e22c247a8d9597b4fc491e6-2", + "0x194a0f84de41d006a07ece07c96a8130100818599fcf0b2ecf49e512b873ed6e-2", + "0x3ecf42927509645dec38667d557dd9ba20d0d07267d769983495c1b6b9c70cc4-2", + "0xf11ccb6079c1a4b3d86abe2c574c5db8d2fd3505fdc1d5970b69b31864a4bd1c-2", + ] }, + { code_hash: "0x577a5e5930e2ecdd6200765f3442e6119dc99e87df474f22f13cab819c80b242", hash_type: "type", + name: "FlashSigner", + dep_type: "dep_group", + tx_hashes: ["0xb66776ff3244033fcd15312ae8b17d384c11bebbb923fce3bd896d89f4744d48-0"] }, + { code_hash: "0x89cd8003a0eaf8e65e0c31525b7d1d5c1becefd2ea75bb4cff87810ae37764d8", hash_type: "type", + name: "CoTA", + dep_type: "dep_group", + description: "A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.", + tx_hashes: [ + "0xd8c7396f955348bd74a8ed4398d896dad931977b7c1e3f117649765cd3d75b86-0", + ] }, + { code_hash: "0x9302db6cc1344b81a5efee06962abcb40427ecfcbe69d471b01b2658ed948075", hash_type: "type", + name: "CoTA Registry", + dep_type: "dep_group", + description: "A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.", + tx_hashes: [ + "0xd8c7396f955348bd74a8ed4398d896dad931977b7c1e3f117649765cd3d75b86-0", + ] }, + { code_hash: "0x85ae4db0dd83f428a31deb342e4000af37ce2c9645d9e619df00096e3c50a2bb", hash_type: "type", + name: "Godwoken Custodian Lock", + dep_type: "code", + description: "Rollup uses the custodian lock to hold the deposited assets.", + tx_hashes: ["0x7aed145beb6984fff008ca6224d0726d06a19959c4f01d15e49942d76e28747a-0"] }, + { code_hash: "0x50704b84ecb4c4b12b43c7acb260ddd69171c21b4c0ba15f3c469b7d143f6f18", hash_type: "type", + name: "Godwoken Deposit Lock", + dep_type: "code", + description: "A layer1 user can join the Rollup by creating a deposit cell.", tx_hashes: ["0x9caeec735f3cd2a60b9d12be59bb161f7c61ddab1ac22c4383a94c33ba6404a2-0"] }, + { code_hash: "0x06ae0706bb2d7997d66224741d3ec7c173dbb2854a6d2cf97088796b677269c6", hash_type: "type", + name: "Godwoken Withdrawal Lock", + dep_type: "code", + description: "Withdrawal cells are generated in the RollupSubmitBlock action according to the block.withdrawals field.", + tx_hashes: ["0x9c607a9a75ea4699dd01b1c2a478002343998cac8346d2aa582f35b532bd2b93-0"] }, + { code_hash: "0x5a86c3bf1e8648b6a6f8abe6875720ccf9745ab225b68fa7c195f9d6635dea80", hash_type: "type", + dep_type: "code", + name: "Godwoken Challenge Lock", + description: "When a Godwoken node found that an invalid state exists in the Rollup, the node can send the RollupEnterChallenge action to the Rollup cell and generate a challenging cell.", + tx_hashes: ["0x15598fb4d3fc4b7e0afcffc80ed0c02b62edb3f7875771f0397f17eef712b65d-0"] }, + { code_hash: "0x7f5a09b8bd0e85bcf2ccad96411ccba2f289748a1c16900b0635c2ed9126f288", hash_type: "type", + name: "Godwoken Stake Lock", + dep_type: "code", + description: "A block producer is required to provide a stake cell to perform the RollupSubmitBlock action.", + tx_hashes: ["0x053fdb4ed3181eab3a3a5f05693b53a8cdec0a24569e16369f444bac48be7de9-0"] }, + { code_hash: "0x1e44736436b406f8e48a30dfbddcf044feb0c9eebfe63b0f81cb5bb727d84854", hash_type: "type", + name: "Godwoken State Validator", + dep_type: "code", + description: "State validator is the major script to verify the on-chain Rollup cell. Rollup cell is an identity cell on CKB, it stores the structure GlobalState which represents the layer-2 state.", + tx_hashes: ["0xbcd73881ba53f1cd95d0c855395c4ffe6f54e041765d9ab7602d48a7cb71612e-0"] }, + { code_hash: "0x07521d0aa8e66ef441ebc31204d86bb23fc83e9edc58c19dbb1b0ebe64336ec0", hash_type: "type", + name: "Godwoken ETH Account Lock", + dep_type: "code", + description: "A layer-2 lock script, ETH account lock is a script that verifies the layer-2 account signature.", + tx_hashes: ["0x21da20f275af89ca7172cb1cd7fcb8676056e4212ba3782e8c77afebae57c6ed-0"] }, + { code_hash: "0x79f90bb5e892d80dd213439eeab551120eb417678824f282b4ffb5f21bad2e1e", hash_type: "type", + name: "OMNI Lock V1", + dep_type: "code", + tx_hashes: ["0x9154df4f7336402114d04495175b37390ce86a4906d2d4001cf02c3e6d97f39c-0"], + description: "Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future." }, + { code_hash: "0xf329effd1c475a2978453c8600e1eaf0bc2087ee093c3ee64cc96ec6847752cb", hash_type: "type", + name: "OMNI Lock V2", + tx_hashes: ["0xec18bf0d857c981c3d1f4e17999b9b90c484b303378e94de1a57b0872f5d4602-0"], + dep_type: "code", + description: "Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future." }, + { code_hash: "0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac", hash_type: "type", + name: "JoyID", + dep_type: "dep_group", + description: "An universal Account Protocol for Web3 Mass-adoption.", + tx_hashes: ["0x4dcf3f3b09efac8995d6cbee87c5345e812d310094651e0c3d9a730f32dc9263-0"] }, + { code_hash: "0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb", hash_type: "type", + name: "xUDT(final_rls)", + description: "Extensible UDT that derived from sUDT's programmability to support a wider range of scenarios", + dep_type: "code", + tx_hashes: ["0xbf6fb538763efec2a70a6a3dcb7242787087e1030c4e7d86585bc63a9d337f5f-0"] }, + { code_hash: "0xbbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c133494", hash_type: "data1", + name: "Spore(v1 latest)", + dep_type: "code", + tx_hashes: ["0xfd694382e621f175ddf81ce91ce2ecf8bfc027d53d7d31b8438f7d26fc37fd19-0"], + description: "Spore Protocol infuses digital assets with enduring value backed by tokenomics, redeemable at any time. Ensures true on-chain ownership, privacy, creative freedom and frictionless interaction." }, + { code_hash: "0x685a60219309029d01310311dba953d67029170ca4848a4ff638e57002130a0d", hash_type: "data1", + name: "Spore(v2 preview)", + dep_type: "code", + tx_hashes: ["0x5e8d2a517d50fd4bb4d01737a7952a1f1d35c8afc77240695bb569cd7d9d5a1f-0"], + description: "Spore Protocol infuses digital assets with enduring value backed by tokenomics, redeemable at any time. Ensures true on-chain ownership, privacy, creative freedom and frictionless interaction." }, + { code_hash: "0x598d793defef36e2eeba54a9b45130e4ca92822e1d193671f490950c3b856080", hash_type: "data1", + name: "Spore Cluster(v1 latest)", + dep_type: "code", + tx_hashes: ["0x49551a20dfe39231e7db49431d26c9c08ceec96a29024eef3acc936deeb2ca76-0"], + description: "" }, + { code_hash: "0x0bbe768b519d8ea7b96d58f1182eb7e6ef96c541fbd9526975077ee09f049058", hash_type: "data1", + name: "Spore Cluster(v2 preview)", + dep_type: "code", + tx_hashes: ["0xcebb174d6e300e26074aea2f5dbd7f694bb4fe3de52b6dfe205e54f90164510a-0"], + description: "" }, + { code_hash: "0x923e997654b2697ee3f77052cb884e98f28799a4270fd412c3edb8f3987ca622", hash_type: "data1", + name: "Spore Cluster Agent(v2 preview)", + dep_type: "code", + tx_hashes: ["0x52210232292d10c51b48e72a2cea60d8f0a08c2680a97a8ee7ca0a39379f0036-0"], + description: "" }, + { code_hash: "0x4349889bda064adab8f49f7dd8810d217917f7df28e9b2a1df0b74442399670a", hash_type: "data1", + name: "Spore Cluster Proxy(v2 preview)", + dep_type: "code", + tx_hashes: ["0xc5a41d58155b11ecd87a5a49fdcb6e83bd6684d3b72b2f3686f081945461c156-0"], + description: "" }, + { code_hash: "0x61ca7a4796a4eb19ca4f0d065cb9b10ddcf002f10f7cbb810c706cb6bb5c3248", hash_type: "type", + name: "RGB++", + dep_type: "code", + description: "RGB++ Lock", + tx_hashes: ["0xf1de59e973b85791ec32debbba08dff80c63197e895eb95d67fc1e9f6b413e00-0"] }, + { code_hash: "0xd07598deec7ce7b5665310386b4abd06a6d48843e953c5cc2112ad0d5a220364", hash_type: "type", + name: "RGB++", + dep_type: "code", + tx_hashes: ["0x61efdeddbaa0bb4132c0eb174b3e8002ff5ec430f61ba46f30768d683c516eec-0"], + description: "RGB++ Lock" }, + { code_hash: "0x8e341bcfec6393dcd41e635733ff2dca00a6af546949f70c57a706c0f344df8b", hash_type: "data1", + name: "Unique Cell", + dep_type: "code", + tx_hashes: ["0xff91b063c78ed06f10a1ed436122bd7d671f9a72ef5f5fa28d05252c17cf4cef-0"], + description: "A unique cell can be created on the Nervos CKB through TypeID which makes sure the unique cell cannot be updated or destroyed." }, + { code_hash: "0x00cdf8fab0f8ac638758ebf5ea5e4052b1d71e8a77b9f43139718621f6849326", hash_type: "type", + name: "Btc Time Lock", + dep_type: "code", + tx_hashes: ["0xde0f87878a97500f549418e5d46d2f7704c565a262aa17036c9c1c13ad638529-0"], + description: "A lock require n confirmations of Bitcoin transaction to unlock the cell." }, + { code_hash: "0x80a09eca26d77cea1f5a69471c59481be7404febf40ee90f886c36a948385b55", hash_type: "type", + name: "Btc Time Lock", + dep_type: "code", + tx_hashes: ["0x5364b3535965e9eac9a35dd7af8e9e45a61d30a16e115923c032f80b28783e21-0"], + description: "A lock require n confirmations of Bitcoin transaction to unlock the cell." }, + { code_hash: "0x0b1f412fbae26853ff7d082d422c2bdd9e2ff94ee8aaec11240a5b34cc6e890f", hash_type: "type", + tx_hashes: ["0x37f82dd30435575954cc7a9e2292f238ed24d71b0d57a55d8a2fc8a08aa1accf-0"], + name: "DID", + dep_type: "code", + description: "" }, + { code_hash: "0x6ae5ee0cb887b2df5a9a18137315b9bdc55be8d52637b2de0624092d5f0c91d5", hash_type: "type", + name: "Nostr", + dep_type: "code", + tx_hashes: ["0xa2a434dcdbe280b9ed75bb7d6c7d68186a842456aba0fc506657dc5ed7c01d68-0"], + description: "The Nostr lock script is designed for interoperability with Nostr." }, + { code_hash: "0x8290467a512e5b9a6b816469b0edabba1f4ac474e28ffdd604c2a7c76446bbaf", hash_type: "data1", + name: "Single Use Lock", + dep_type: "code", + tx_hashes: ["0xb4f171c9c9caf7401f54a8e56225ae21d95032150a87a4678eac3f66a3137b93-4"], + description: "A lock script that can only be used once." }, + { code_hash: "0x2a8100ab5990fa055ab1b50891702e1e895c7bd1df6322cd725c1a6115873bd3", hash_type: "data1", + name: "iCKB Logic", + dep_type: "dep_group", + tx_hashes: ["0xf7ece4fb33d8378344cab11fcd6a4c6f382fd4207ac921cf5821f30712dcd311-0"], + description: "iCKB Logic tokenizes NervosDAO deposits into the iCKB xUDT token." }, + { code_hash: "0xacc79e07d107831feef4c70c9e683dac5644d5993b9cb106dca6e74baa381bd0", hash_type: "data1", + name: "WR Owned-Owner", + dep_type: "dep_group", + tx_hashes: ["0xf7ece4fb33d8378344cab11fcd6a4c6f382fd4207ac921cf5821f30712dcd311-0"], + description: + "WR Owned-Owner enable to create Withdrawals Request from NervosDAO deposits locked with zero length args locks, developed as part of iCKB." }, + { code_hash: "0x49dfb6afee5cc8ac4225aeea8cb8928b150caf3cd92fea33750683c74b13254a", hash_type: "data1", + name: "UDT Limit Orderr", + dep_type: "dep_group", + tx_hashes: ["0xf7ece4fb33d8378344cab11fcd6a4c6f382fd4207ac921cf5821f30712dcd311-0"], + description: "UDT Limit Order is a general purpose UDT based Limit Order, developed as part of iCKB." }, + ] + end + + error_hashes = [] + hashes.each do |hash| + case hash[:dep_type] + when "code" + hash[:tx_hashes].each do |tx| + tx_hash, cell_index = tx.split("-") + co = CellOutput.find_by(tx_hash:, cell_index:) + contract = Contract.find_by(deployed_cell_output_id: co.id) + contract.update(verified: true, name: hash[:name], description: hash[:description], hash_type: hash[:hash_type], deprecated: hash[:deprecated]) + end + when "dep_group" + hash[:tx_hashes].each do |tx| + tx_hash, cell_index = tx.split("-") + contract_cell = CellOutput.find_by(tx_hash:, cell_index:) + deployed_ids = CellDepsOutPoint.where(contract_cell_id: contract_cell.id).pluck(:deployed_cell_output_id) + contract = + if hash[:hash_type] == "type" + Contract.where(deployed_cell_output_id: deployed_ids).where(type_hash: hash[:code_hash]) + else + Contract.where(deployed_cell_output_id: deployed_ids).where(data_hash: hash[:code_hash]) + end + if contract.length == 1 + contract.first.update(verified: true, name: hash[:name], description: hash[:description], hash_type: hash[:hash_type], deprecated: hash[:deprecated]) + else + error_hashes << hash[:code_hash] + end + end + end + rescue StandardError => e + puts e.inspect + error_hashes << hash[:tx_hashes] + end + puts error_hashes.join(",") + end + + puts "done" +end diff --git a/lib/tasks/migration/init_contracts.rake b/lib/tasks/migration/init_contracts.rake deleted file mode 100644 index 47b26ca12..000000000 --- a/lib/tasks/migration/init_contracts.rake +++ /dev/null @@ -1,54 +0,0 @@ -namespace :migration do - desc "Usage: RAILS_ENV=production bundle exec rake migration:init_contracts" - task init_contracts: :environment do - ApplicationRecord.transaction do - if ENV['CKB_NET_MODE'] == 'mainnet' - hashes = [ - { code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', hash_type: 'type', name: 'SECP256K1/blake160', description: 'SECP256K1/blake160 is the default lock script to verify CKB transaction signature.', role: 'lock_script' }, - { code_hash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8', hash_type: 'type', name: 'SECP256K1/multisig', description: 'SECP256K1/multisig is a script which allows a group of users to sign a single transaction.', role: 'lock_script' }, - { code_hash: '0xd369597ff47f29fbc0d47d2e3775370d1250b85140c670e4718af712983a2354', hash_type: 'type', name: 'Anyone-Can-Pay Lock', description: 'anyone_can_pay allows a recipient to provide cell capacity in asset transfer.', role: 'type_script' }, - { code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e', hash_type: 'type', name: 'Nervos DAO', description: 'Nervos DAO is a smart contract with which users can interact the same way as any smart contract on CKB.', role: 'type_script' }, - { code_hash: '0x5e7a36a77e68eecc013dfa2fe6a23f3b6c344b04005808694ae6dd45eea4cfd5', hash_type: 'type', name: 'Simple UDT', description: 'Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB.', role: 'type_script' }, - { code_hash: '0xd01f5152c267b7f33b9795140c2467742e8424e49ebe2331caec197f7281b60a', hash_type: 'type', name: 'Unipass', description: 'Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB.', role: 'type_script' }, - { code_hash: '0x1122a4fb54697cf2e6e3a96c9d80fd398a936559b90954c6e88eb7ba0cf652df', hash_type: 'type', name: 'CoTA', description: 'A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.', role: 'type_script' }, - { code_hash: '0x90ca618be6c15f5857d3cbd09f9f24ca6770af047ba9ee70989ec3b229419ac7', hash_type: 'type', name: 'CoTA Registry', description: 'A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.', role: 'type_script' }, - { code_hash: '0xbf43c3602455798c1a61a596e0d95278864c552fafe231c063b3fabf97a8febc', hash_type: 'type', name: 'PW Lock', description: "Forked from CKB's system scripts, and currently supports signature generated by personalSign and signTypedData from ethereum wallets.", role: 'type_script' }, - { code_hash: '0x000f87062a2fe9bb4a6cc475212ea11014b84deb32e0375ee51e6ec4a553e009', hash_type: 'type', name: 'godwoken_custodian_lock', description: 'Rollup uses the custodian lock to hold the deposited assets.', role: 'type_script' }, - { code_hash: '0xff602581f07667eef54232cce850cbca2c418b3418611c132fca849d1edcd775', hash_type: 'type', name: 'godwoken_deposit_lock', description: 'A layer1 user can join the Rollup by creating a deposit cell.', role: 'type_script' }, - { code_hash: '0x3714af858b8b82b2bb8f13d51f3cffede2dd8d352a6938334bb79e6b845e3658', hash_type: 'type', name: 'godwoken_withdrawal_lock', description: 'Withdrawal cells are generated in the RollupSubmitBlock action according to the block.withdrawals field.', role: 'type_script' }, - { code_hash: '0x628b5f956b46ae27b50819a9ebab79ce5f957e6899ba0c75b8e142de2ed0dcd2', hash_type: 'type', name: 'godwoken_challenge_lock', description: 'When a Godwoken node found that an invalid state exists in the Rollup, the node can send the RollupEnterChallenge action to the Rollup cell and generate a challenging cell.' }, - { code_hash: '0xb619184ab9142c51b0ee75f4e24bcec3d077eefe513115bad68836d06738fd2c', hash_type: 'type', name: 'godwoken_stake_lock', description: 'A block producer is required to provide a stake cell to perform the RollupSubmitBlock action.', role: 'type_script' }, - { code_hash: '0xa4398768d87bd17aea1361edc3accd6a0117774dc4ebc813bfa173e8ac0d086d', hash_type: 'type', name: 'omni_lock v1', description: 'Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future.', role: 'lock_script' }, - { code_hash: '0x9b819793a64463aed77c615d6cb226eea5487ccfc0783043a587254cda2b6f26', hash_type: 'type', name: 'omni_lock v2', description: 'Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future.', role: 'lock_script' }, - { code_hash: '0xfef1d086d9f74d143c60bf03bd04bab29200dbf484c801c72774f2056d4c6718', hash_type: 'type', name: 'godwoken_state_validator', description: 'State validator is the major script to verify the on-chain Rollup cell. Rollup cell is an identity cell on CKB, it stores the structure GlobalState which represents the layer-2 state.', role: 'type_script' }, - { code_hash: '0x096df264f38fff07f3acd318995abc2c71ae0e504036fe32bc38d5b6037364d4', hash_type: 'type', name: 'godwoken_eth_account_lock', description: 'A layer-2 lock script, ETH account lock is a script that verifies the layer-2 account signature.', role: 'type_script' } - ] - else - hashes = [ - { code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', hash_type: 'type', name: 'SECP256K1/blake160', description: 'SECP256K1/blake160 is the default lock script to verify CKB transaction signature.', role:'lock_script' }, - { code_hash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8', hash_type: 'type', name: 'SECP256K1/multisig', description: 'SECP256K1/multisig is a script which allows a group of users to sign a single transaction.', role:'lock_script' }, - { code_hash: '0x3419a1c09eb2567f6552ee7a8ecffd64155cffe0f1796e6e61ec088d740c1356', hash_type: 'type', name: 'Anyone-Can-Pay Lock', description: 'anyone_can_pay allows a recipient to provide cell capacity in asset transfer.', role: 'type_script' }, - { code_hash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e', hash_type: 'type', name: 'Nervos DAO', description: 'Nervos DAO is a smart contract with which users can interact the same way as any smart contract on CKB.', role: 'type_script' }, - { code_hash: '0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4', hash_type: 'type', name: 'Simple UDT', description: 'Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB.' , role: 'type_script'}, - { code_hash: '0x3e1eb7ed4809b2d60650be96a40abfbdafb3fb942b7b37ec7709e64e2cd0a783', hash_type: 'type', name: 'Unipass', description: 'Simple UDT provides a way for dapp developers to issue custom tokens on Nervos CKB.', role: 'type_script' }, - { code_hash: '0x89cd8003a0eaf8e65e0c31525b7d1d5c1becefd2ea75bb4cff87810ae37764d8', hash_type: 'type', name: 'CoTA', description: 'A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.', role: 'type_script' }, - { code_hash: '0x9302db6cc1344b81a5efee06962abcb40427ecfcbe69d471b01b2658ed948075', hash_type: 'type', name: 'CoTA Registry', description: 'A Compact Token Aggregator Standard for Extremely Low Cost NFTs and FTs.', role: 'type_script', role: 'type_script' }, - { code_hash: '0x58c5f491aba6d61678b7cf7edf4910b1f5e00ec0cde2f42e0abb4fd9aff25a63', hash_type: 'type', name: 'PW Lock', description: "Forked from CKB's system scripts, and currently supports signature generated by personalSign and signTypedData from ethereum wallets.", role: 'type_script' }, - { code_hash: '0x85ae4db0dd83f428a31deb342e4000af37ce2c9645d9e619df00096e3c50a2bb', hash_type: 'type', name: 'godwoken_custodian_lock', description: 'Rollup uses the custodian lock to hold the deposited assets.', role: 'type_script' }, - { code_hash: '0x50704b84ecb4c4b12b43c7acb260ddd69171c21b4c0ba15f3c469b7d143f6f18', hash_type: 'type', name: 'godwoken_deposit_lock', description: 'A layer1 user can join the Rollup by creating a deposit cell.', role: 'type_script' }, - { code_hash: '0x06ae0706bb2d7997d66224741d3ec7c173dbb2854a6d2cf97088796b677269c6', hash_type: 'type', name: 'godwoken_withdrawal_lock', description: 'Withdrawal cells are generated in the RollupSubmitBlock action according to the block.withdrawals field.', role: 'type_script' }, - { code_hash: '0x5a86c3bf1e8648b6a6f8abe6875720ccf9745ab225b68fa7c195f9d6635dea80', hash_type: 'type', name: 'godwoken_challenge_lock', description: 'When a Godwoken node found that an invalid state exists in the Rollup, the node can send the RollupEnterChallenge action to the Rollup cell and generate a challenging cell.', role: 'type_script', role: 'type_script' }, - { code_hash: '0x7f5a09b8bd0e85bcf2ccad96411ccba2f289748a1c16900b0635c2ed9126f288', hash_type: 'type', name: 'godwoken_stake_lock', description: 'A block producer is required to provide a stake cell to perform the RollupSubmitBlock action.', role: 'type_script' }, - { code_hash: '0x79f90bb5e892d80dd213439eeab551120eb417678824f282b4ffb5f21bad2e1e', hash_type: 'type', name: 'omni_lock v1', description: 'Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future.', role: 'lock_script' }, - { code_hash: '0xf329effd1c475a2978453c8600e1eaf0bc2087ee093c3ee64cc96ec6847752cb', hash_type: 'type', name: 'omni_lock v2', description: 'Omnilock is a lock script designed for interoperability. It comes with built-in support for verification of transaction signing methods used in Bitcoin, Ethereum, EOS, and Dogecoin. Omnilock is also extensible, so more verification algorithms can be added in future.', role: 'lock_script' }, - { code_hash: '0x1e44736436b406f8e48a30dfbddcf044feb0c9eebfe63b0f81cb5bb727d84854', hash_type: 'type', name: 'godwoken_state_validator', description: 'State validator is the major script to verify the on-chain Rollup cell. Rollup cell is an identity cell on CKB, it stores the structure GlobalState which represents the layer-2 state.', role: 'type_script' }, - { code_hash: '0x07521d0aa8e66ef441ebc31204d86bb23fc83e9edc58c19dbb1b0ebe64336ec0', hash_type: 'type', name: 'godwoken_eth_account_lock', description: 'A layer-2 lock script, ETH account lock is a script that verifies the layer-2 account signature.', role: 'type_script' } - ] - end - - hashes.each {|hash| Contract.create(hash) unless Contract.exists?(code_hash: hash[:code_hash]) } - end - - puts "done" - end -end diff --git a/test/controllers/api/v2/scripts_controller_test.rb b/test/controllers/api/v2/scripts_controller_test.rb index f9f0c3cdc..5cdbd8786 100644 --- a/test/controllers/api/v2/scripts_controller_test.rb +++ b/test/controllers/api/v2/scripts_controller_test.rb @@ -7,18 +7,11 @@ class ScriptsControllerTest < ActionDispatch::IntegrationTest @code_hash = "0x00000000000000000000000000000000000000000000000000545950455f4944" @hash_type = "type" @block = create :block - @contract = create :contract, code_hash: @code_hash, hash_type: @hash_type - @script = create :script, contract_id: @contract.id - @type_script = create :type_script, code_hash: @code_hash, hash_type: @hash_type, script_id: @script.id + @type_script = create :type_script, code_hash: @code_hash, hash_type: @hash_type @cell_output1 = create :cell_output, :with_full_transaction, block: @block @cell_output2 = create :cell_output, :with_full_transaction, block: @block @cell_output3 = create :cell_output, :with_full_transaction, block: @block - create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output1.id - create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output2.id - create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output3.id - create :referring_cell, contract_id: @contract.id, cell_output_id: @cell_output1.id, ckb_transaction_id: @cell_output1.ckb_transaction_id - create :referring_cell, contract_id: @contract.id, cell_output_id: @cell_output2.id, ckb_transaction_id: @cell_output2.ckb_transaction_id - create :referring_cell, contract_id: @contract.id, cell_output_id: @cell_output3.id, ckb_transaction_id: @cell_output3.ckb_transaction_id + @contract = create :contract, type_hash: @code_hash, hash_type: @hash_type, deployed_cell_output_id: @cell_output1.id end test "should get ckb_transactions" do diff --git a/test/controllers/api/v2/statistics_controller_test.rb b/test/controllers/api/v2/statistics_controller_test.rb index 146ed6dfd..9fd30f0de 100644 --- a/test/controllers/api/v2/statistics_controller_test.rb +++ b/test/controllers/api/v2/statistics_controller_test.rb @@ -101,7 +101,7 @@ class StatisticsControllerTest < ActionDispatch::IntegrationTest test "return contracts resource distributed with code_hashes params" do contracts = create_list(:contract, 3) - get contract_resource_distributed_api_v2_statistics_url, params: { code_hashes: "#{contracts[0].code_hash},#{contracts[1].code_hash}" } + get contract_resource_distributed_api_v2_statistics_url, params: { code_hashes: "#{contracts[0].type_hash},#{contracts[1].type_hash}" } data = JSON.parse(response.body) assert_equal 2, data.size diff --git a/test/factories/cell_dependency.rb b/test/factories/cell_dependency.rb index e0e254b6b..9600deaa7 100644 --- a/test/factories/cell_dependency.rb +++ b/test/factories/cell_dependency.rb @@ -1,5 +1,5 @@ FactoryBot.define do factory :cell_dependency do - dep_type { :dep_group } + dep_type { :code } end end diff --git a/test/factories/cell_deps_out_point.rb b/test/factories/cell_deps_out_point.rb new file mode 100644 index 000000000..0781a3bc1 --- /dev/null +++ b/test/factories/cell_deps_out_point.rb @@ -0,0 +1,6 @@ +FactoryBot.define do + factory :cell_deps_out_point do + contract_cell_id { 1 } + deployed_cell_output_id { 1 } + end +end diff --git a/test/factories/contract.rb b/test/factories/contract.rb index 8e9114029..5ab58ae13 100644 --- a/test/factories/contract.rb +++ b/test/factories/contract.rb @@ -1,6 +1,5 @@ FactoryBot.define do factory :contract do - code_hash { "0x#{SecureRandom.hex(32)}" } hash_type { "type" } deployed_args { "0x#{SecureRandom.hex(32)}" } role { "type_script" } @@ -12,18 +11,19 @@ total_referring_cells_capacity { SecureRandom.random_number(10**10) } ckb_transactions_count { SecureRandom.random_number(10**10) } addresses_count { SecureRandom.random_number(100_000_000) } + type_hash { "0x#{SecureRandom.hex(32)}" } after(:create) do |contract, _eval| tx = create :ckb_transaction, :with_single_output co = tx.cell_outputs.first case contract.hash_type when "type" - co.create_type_script code_hash: "0x00000000000000000000000000000000000000000000000000545950455f4944", hash_type: "type", script_hash: contract.code_hash + co.create_type_script code_hash: "0x00000000000000000000000000000000000000000000000000545950455f4944", hash_type: "type", script_hash: contract.type_hash when "data" co.update data_hash: contract.code_hash end - script = create :script, contract_id: contract.id, is_contract: true - contract.deployed_cells.create cell_output_id: co.id + contract.deployed_cell_output_id = co.id + contract.save end end end diff --git a/test/models/cell_dependency_test.rb b/test/models/cell_dependency_test.rb index 0db0ca87b..cf83a59d9 100644 --- a/test/models/cell_dependency_test.rb +++ b/test/models/cell_dependency_test.rb @@ -2,34 +2,22 @@ class CellDependencyTest < ActiveSupport::TestCase context "associations" do - should belong_to(:script) should belong_to(:cell_output) should belong_to(:ckb_transaction) end setup do - @contract = create :contract @block = create(:block, :with_block_hash) @ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: @block) @cell_output = create :cell_output, :with_full_transaction, block: @block - @script = create :script - @cell_dependency = create :cell_dependency, contract_id: @contract.id, ckb_transaction_id: @ckb_transaction.id, contract_cell_id: @cell_output.id, - script_id: @script.id + @contract = create :contract, deployed_cell_output_id: @cell_output.id + @cell_dependency = create :cell_dependency, ckb_transaction_id: @ckb_transaction.id, contract_cell_id: @cell_output.id + create :cell_deps_out_point, contract_cell_id: @cell_output.id, deployed_cell_output_id: @cell_output.id end test "it should create contract" do - assert_equal @contract.id, @cell_dependency.contract_id - assert_equal "dep_group", @cell_dependency.dep_type + assert_equal "code", @cell_dependency.dep_type assert_equal @cell_output.id, @cell_dependency.contract_cell_id assert_equal @ckb_transaction.id, @cell_dependency.ckb_transaction_id end - - test "it should update contract" do - @cell_dependency.update dep_type: :dep_group - assert_equal "dep_group", @cell_dependency.dep_type - end - - test "it should belongs_to contract" do - assert_equal @contract, @cell_dependency.contract - end end diff --git a/test/models/ckb_sync/node_data_processor_test.rb b/test/models/ckb_sync/node_data_processor_test.rb index f9b790284..a6d3b34fe 100644 --- a/test/models/ckb_sync/node_data_processor_test.rb +++ b/test/models/ckb_sync/node_data_processor_test.rb @@ -4168,11 +4168,21 @@ class NodeDataProcessorTest < ActiveSupport::TestCase number: node_block.header.number - 1) tx1 = create(:ckb_transaction, block: block1, tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + tx2 = create(:ckb_transaction, block: block1, + tx_hash: "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37") + tx3 = create(:ckb_transaction, block: block1, + tx_hash: "0x2415ee81413fa9dd82245db054c19eb1ae2191185e2cb18ed1262947aec323c3") + tx4 = create(:ckb_transaction, block: block1, + tx_hash: "0xbf6fb538763efec2a70a6a3dcb7242787087e1030c4e7d86585bc63a9d337f5f") + input_address1 = create(:address) address1_lock = create(:lock_script, address_id: input_address1.id, args: "0x#{SecureRandom.hex(20)}", code_hash: Settings.secp_cell_type_hash, hash_type: "type") + create :cell_output, ckb_transaction: tx2, tx_hash: tx2.tx_hash, cell_index: 0, lock_script_id: address1_lock.id + create :cell_output, ckb_transaction: tx3, tx_hash: tx3.tx_hash, cell_index: 0, lock_script_id: address1_lock.id + create :cell_output, ckb_transaction: tx4, tx_hash: tx4.tx_hash, cell_index: 0, lock_script_id: address1_lock.id output1 = create(:cell_output, ckb_transaction: tx1, block: block1, capacity: 50000000 * 10**8, tx_hash: tx1.tx_hash, @@ -4192,6 +4202,7 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_equal 8, xudt.decimal assert_equal "xudt", xudt.udt_type assert_equal "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqga7eurwgfm534kew3092y28sp3mwlqpqcptqy24", xudt.issuer_address + assert_equal 3, CellDependency.count ENV["CKB_NET_MODE"] = "mainnet" end end diff --git a/test/models/contract_test.rb b/test/models/contract_test.rb index aa028f146..569a53005 100644 --- a/test/models/contract_test.rb +++ b/test/models/contract_test.rb @@ -6,10 +6,6 @@ class ContractTest < ActiveSupport::TestCase end context "associations" do - should have_many(:referring_cells) - should have_many(:deployed_cells) - should have_many(:scripts) - should have_many(:ckb_transactions) should have_many(:cell_dependencies) end @@ -25,7 +21,8 @@ class ContractTest < ActiveSupport::TestCase end test "it should update contract" do - @contract.update deprecated: true, verified: true, hash_type: 'type1', code_hash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a81', name: 'CKB COIN TEST1', role: 'lock_script', symbol: 'TTF1', deployed_args: '0x284c65a608e8e280aaa9c119a1a8fe0463a171511', description: 'Source Code is a script which allows a group of users to sign a single transaction.' + @contract.update deprecated: true, verified: true, hash_type: "type1", code_hash: "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a81", name: "CKB COIN TEST1", + role: "lock_script", symbol: "TTF1", deployed_args: "0x284c65a608e8e280aaa9c119a1a8fe0463a171511", description: "Source Code is a script which allows a group of users to sign a single transaction." assert_equal true, @contract.verified assert_equal true, @contract.deprecated assert_equal "type1", @contract.hash_type @@ -36,15 +33,4 @@ class ContractTest < ActiveSupport::TestCase assert_equal "CKB COIN TEST1", @contract.name assert_equal "TTF1", @contract.symbol end - test "it should create initial data" do - Script.delete_all - LockScript.delete_all - TypeScript.delete_all - create :lock_script - create :type_script - Script.create_initial_data - Contract.create_initial_data - assert_equal 3, Contract.count - end - end diff --git a/test/models/deployed_cell_test.rb b/test/models/deployed_cell_test.rb index 8a301d744..06ba4d5a4 100644 --- a/test/models/deployed_cell_test.rb +++ b/test/models/deployed_cell_test.rb @@ -1,172 +1,172 @@ require "test_helper" -class DeployedCellTest < ActiveSupport::TestCase - context "associations" do - should belong_to(:contract) - should belong_to(:cell_output) - end - - setup do - @block = create :block, :with_block_hash - @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block_id: @block.id - - code_hash = "0x671ddda336db68ce0daebde885f44e2f46406d6c838484b4bd8934173e518876" - @cell_output = create :cell_output, :with_full_transaction, ckb_transaction_id: @ckb_transaction.id, block: @block, - data: "0x", data_hash: code_hash - @contract = create :contract - @deployed_cell = create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output.id - CellOutput.stubs(:find_by_pointer).returns(@cell_output) - CellOutput.any_instance.stubs(:data_hash).returns(code_hash) - CellOutput.any_instance.stubs(:type_hash).returns(code_hash) - end - - test "it should create deployed_cell" do - assert_equal @cell_output.id, @deployed_cell.cell_output_id - assert_equal @contract.id, @deployed_cell.contract_id - end - - test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is type" do - # step 1 delete redundant data - delete_redundant_data - - # step 2 prepare test data - prepare_test_data_for_hash_type_for_cell_outputs - - # step 3 start unit test - # for the 1st time, it will create - DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - @deployed_cell = DeployedCell.first - contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id - assert_equal 1, DeployedCell.all.count - assert_equal contract_id, @deployed_cell.contract_id - - # for the 2nd time, it should NOT create record - DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - assert_equal 1, DeployedCell.all.count - end - - test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is data" do - # step 1 delete redundant data - delete_redundant_data - # step 2 prepare test data - prepare_test_data_for_hash_type_for_cell_outputs hash_type: "data" - # step 3 start unit test - # for the 1st time, it will create - DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - @deployed_cell = DeployedCell.first - contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id - assert_equal 1, DeployedCell.all.count - assert_equal contract_id, @deployed_cell.contract_id - - # for the 2nd time, it should NOT create record - # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps - assert_equal 1, DeployedCell.all.count - end - - test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is type" do - # step 1 delete redundant data - delete_redundant_data - - # step 2 prepare test data - prepare_test_data_for_hash_type_for_cell_inputs - - # step 3 start unit test - # for the 1st time, it will create - # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps - @deployed_cell = DeployedCell.first - contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id - assert_equal contract_id, @deployed_cell.contract_id - assert_equal 1, DeployedCell.all.count - - # for the 2nd time, it should NOT create record - DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - assert_equal 1, DeployedCell.all.count - end - - test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is data" do - # step 1 delete redundant data - delete_redundant_data - # step 2 prepare test data - prepare_test_data_for_hash_type_for_cell_inputs hash_type: "data" - # step 3 start unit test - # for the 1st time, it will create - # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - @deployed_cell = DeployedCell.first - contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id - assert_equal contract_id, @deployed_cell.contract_id - assert_equal 1, DeployedCell.all.count - - # for the 2nd time, it should NOT create record - DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps - assert_equal 1, DeployedCell.all.count - end - - private - - def delete_redundant_data - Script.delete_all - ScriptTransaction.delete_all - Contract.delete_all - DeployedCell.delete_all - CkbTransaction.delete_all - Block.delete_all - end - - def prepare_test_data_for_hash_type_for_cell_outputs(hash_type: "type") - @contract = create :contract, hash_type: hash_type - # CKB::Blake2b.hexdigest('0x010200000000008d01f3') - @deployed_cell = @contract.deployed_cells.first - code_hash = @contract.code_hash - tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash - cell_deps = @cell_deps = [ - { - "dep_type" => "code", - "out_point" => { - "index" => @deployed_cell.cell_output.cell_index, - "tx_hash" => tx_hash } } - ] - - block = create :block, :with_block_hash - @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps - CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all - script = create :script, contract_id: @contract.id, is_contract: true - type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script: script - lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script: script - # create test data: cell_outputs - cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, - lock_script: lock_script, type_script: type_script - end - - def prepare_test_data_for_hash_type_for_cell_inputs(hash_type: "type") - @contract = create :contract, hash_type: hash_type - @deployed_cell = @contract.deployed_cells.first - code_hash = @contract.code_hash - tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash - cell_deps = @cell_deps = [ - { - "dep_type" => "code", - "out_point" => { - "index" => @deployed_cell.cell_output.cell_index, - "tx_hash" => tx_hash } } - ] - - block = create :block, :with_block_hash - @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps - CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all - script = create :script, contract_id: @contract.id, is_contract: true - type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id - lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id - # create test data: cell_outputs - cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, - lock_script: lock_script, type_script: type_script - temp_ckb_transaction = CkbTransaction.first - temp_ckb_transaction.update tx_hash: tx_hash - temp_cell_output = create :cell_output, :with_full_transaction, block: block, ckb_transaction: temp_ckb_transaction - temp_cell_output.lock_script.update script_id: script.id - - cell_input = create :cell_input, :with_full_transaction, block: block, - ckb_transaction: @ckb_transaction_with_cell_deps - cell_input.update ckb_transaction_id: @ckb_transaction_with_cell_deps.id, previous_cell_output_id: cell_output.id - cell_input.previous_cell_output.lock_script.update script_id: script.id - end -end +# class DeployedCellTest < ActiveSupport::TestCase +# context "associations" do +# should belong_to(:contract) +# should belong_to(:cell_output) +# end + +# setup do +# @block = create :block, :with_block_hash +# @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block_id: @block.id + +# code_hash = "0x671ddda336db68ce0daebde885f44e2f46406d6c838484b4bd8934173e518876" +# @cell_output = create :cell_output, :with_full_transaction, ckb_transaction_id: @ckb_transaction.id, block: @block, +# data: "0x", data_hash: code_hash +# @contract = create :contract +# @deployed_cell = create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output.id +# CellOutput.stubs(:find_by_pointer).returns(@cell_output) +# CellOutput.any_instance.stubs(:data_hash).returns(code_hash) +# CellOutput.any_instance.stubs(:type_hash).returns(code_hash) +# end + +# test "it should create deployed_cell" do +# assert_equal @cell_output.id, @deployed_cell.cell_output_id +# assert_equal @contract.id, @deployed_cell.contract_id +# end + +# test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is type" do +# # step 1 delete redundant data +# delete_redundant_data + +# # step 2 prepare test data +# prepare_test_data_for_hash_type_for_cell_outputs + +# # step 3 start unit test +# # for the 1st time, it will create +# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# @deployed_cell = DeployedCell.first +# contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id +# assert_equal 1, DeployedCell.all.count +# assert_equal contract_id, @deployed_cell.contract_id + +# # for the 2nd time, it should NOT create record +# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# assert_equal 1, DeployedCell.all.count +# end + +# test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is data" do +# # step 1 delete redundant data +# delete_redundant_data +# # step 2 prepare test data +# prepare_test_data_for_hash_type_for_cell_outputs hash_type: "data" +# # step 3 start unit test +# # for the 1st time, it will create +# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# @deployed_cell = DeployedCell.first +# contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id +# assert_equal 1, DeployedCell.all.count +# assert_equal contract_id, @deployed_cell.contract_id + +# # for the 2nd time, it should NOT create record +# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps +# assert_equal 1, DeployedCell.all.count +# end + +# test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is type" do +# # step 1 delete redundant data +# delete_redundant_data + +# # step 2 prepare test data +# prepare_test_data_for_hash_type_for_cell_inputs + +# # step 3 start unit test +# # for the 1st time, it will create +# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps +# @deployed_cell = DeployedCell.first +# contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id +# assert_equal contract_id, @deployed_cell.contract_id +# assert_equal 1, DeployedCell.all.count + +# # for the 2nd time, it should NOT create record +# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# assert_equal 1, DeployedCell.all.count +# end + +# test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is data" do +# # step 1 delete redundant data +# delete_redundant_data +# # step 2 prepare test data +# prepare_test_data_for_hash_type_for_cell_inputs hash_type: "data" +# # step 3 start unit test +# # for the 1st time, it will create +# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# @deployed_cell = DeployedCell.first +# contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id +# assert_equal contract_id, @deployed_cell.contract_id +# assert_equal 1, DeployedCell.all.count + +# # for the 2nd time, it should NOT create record +# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps +# assert_equal 1, DeployedCell.all.count +# end + +# private + +# def delete_redundant_data +# Script.delete_all +# ScriptTransaction.delete_all +# Contract.delete_all +# DeployedCell.delete_all +# CkbTransaction.delete_all +# Block.delete_all +# end + +# def prepare_test_data_for_hash_type_for_cell_outputs(hash_type: "type") +# @contract = create :contract, hash_type: hash_type +# # CKB::Blake2b.hexdigest('0x010200000000008d01f3') +# @deployed_cell = @contract.deployed_cells.first +# code_hash = @contract.code_hash +# tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash +# cell_deps = @cell_deps = [ +# { +# "dep_type" => "code", +# "out_point" => { +# "index" => @deployed_cell.cell_output.cell_index, +# "tx_hash" => tx_hash } } +# ] + +# block = create :block, :with_block_hash +# @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps +# CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all +# script = create :script, contract_id: @contract.id, is_contract: true +# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script: script +# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script: script +# # create test data: cell_outputs +# cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, +# lock_script: lock_script, type_script: type_script +# end + +# def prepare_test_data_for_hash_type_for_cell_inputs(hash_type: "type") +# @contract = create :contract, hash_type: hash_type +# @deployed_cell = @contract.deployed_cells.first +# code_hash = @contract.code_hash +# tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash +# cell_deps = @cell_deps = [ +# { +# "dep_type" => "code", +# "out_point" => { +# "index" => @deployed_cell.cell_output.cell_index, +# "tx_hash" => tx_hash } } +# ] + +# block = create :block, :with_block_hash +# @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps +# CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all +# script = create :script, contract_id: @contract.id, is_contract: true +# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id +# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id +# # create test data: cell_outputs +# cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, +# lock_script: lock_script, type_script: type_script +# temp_ckb_transaction = CkbTransaction.first +# temp_ckb_transaction.update tx_hash: tx_hash +# temp_cell_output = create :cell_output, :with_full_transaction, block: block, ckb_transaction: temp_ckb_transaction +# temp_cell_output.lock_script.update script_id: script.id + +# cell_input = create :cell_input, :with_full_transaction, block: block, +# ckb_transaction: @ckb_transaction_with_cell_deps +# cell_input.update ckb_transaction_id: @ckb_transaction_with_cell_deps.id, previous_cell_output_id: cell_output.id +# cell_input.previous_cell_output.lock_script.update script_id: script.id +# end +# end diff --git a/test/models/script_test.rb b/test/models/script_test.rb index e9898fcf1..308d54552 100644 --- a/test/models/script_test.rb +++ b/test/models/script_test.rb @@ -1,33 +1,33 @@ require "test_helper" -class ScriptTest < ActiveSupport::TestCase - setup do - @script = create :script - # create for @cell_dependency - @block = create :block, :with_block_hash - @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block: @block - @cell_output = create :cell_output, :with_full_transaction, block: @block - @cell_dependency = create :cell_dependency, ckb_transaction_id: @ckb_transaction.id, contract_cell_id: @cell_output.id, - script_id: @script.id - end +# class ScriptTest < ActiveSupport::TestCase +# setup do +# @script = create :script +# # create for @cell_dependency +# @block = create :block, :with_block_hash +# @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block: @block +# @cell_output = create :cell_output, :with_full_transaction, block: @block +# @cell_dependency = create :cell_dependency, ckb_transaction_id: @ckb_transaction.id, contract_cell_id: @cell_output.id, +# script_id: @script.id +# end - context "associations" do - should have_many(:type_scripts) - should have_many(:cell_dependencies) - should have_many(:ckb_transactions) - should have_many(:lock_scripts) - should have_many(:script_transactions) - end +# context "associations" do +# should have_many(:type_scripts) +# should have_many(:cell_dependencies) +# should have_many(:ckb_transactions) +# should have_many(:lock_scripts) +# should have_many(:script_transactions) +# end - test "create script" do - assert_equal false, @script.is_contract - assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f01855", @script.script_hash - end +# test "create script" do +# assert_equal false, @script.is_contract +# assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f01855", @script.script_hash +# end - test "update script" do - @script.update is_contract: true, args: "0x441714e000fedf3247292c7f34fb16db14f49d9f1", script_hash: "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551" - assert_equal true, @script.is_contract - assert_equal "0x441714e000fedf3247292c7f34fb16db14f49d9f1", @script.args - assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551", @script.script_hash - end -end +# test "update script" do +# @script.update is_contract: true, args: "0x441714e000fedf3247292c7f34fb16db14f49d9f1", script_hash: "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551" +# assert_equal true, @script.is_contract +# assert_equal "0x441714e000fedf3247292c7f34fb16db14f49d9f1", @script.args +# assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551", @script.script_hash +# end +# end diff --git a/test/models/script_transaction_test.rb b/test/models/script_transaction_test.rb index c2120b05d..a83aed7b0 100644 --- a/test/models/script_transaction_test.rb +++ b/test/models/script_transaction_test.rb @@ -1,61 +1,61 @@ require "test_helper" -class ScriptTransactionTest < ActiveSupport::TestCase - setup do - @contract = create :contract - @block = create(:block, :with_block_hash) - @script = create :script, contract_id: @contract.id - @ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: @block) - @script_transaction = create :script_transaction, script_id: @script.id, ckb_transaction_id: @ckb_transaction.id - end - - context "associations" do - should belong_to(:script) - should belong_to(:ckb_transaction) - end - - test "it should create script_transaction" do - assert_equal @ckb_transaction.id, @script_transaction.ckb_transaction_id - assert_equal @script.id, @script_transaction.script_id - end - - test "it should update script_transaction" do - @script_transaction.update ckb_transaction_id: @ckb_transaction.id - 1, script_id: @script.id - 1 - assert_equal @ckb_transaction.id - 1, @script_transaction.ckb_transaction_id - assert_equal @script.id - 1, @script_transaction.script_id - end - - test "it should create_initial_data" do - TypeScript.delete_all - LockScript.delete_all - Script.delete_all - ScriptTransaction.delete_all - Block.delete_all - Contract.delete_all - CellOutput.delete_all - - hash_type = 'type' - code_hash = "0x1c04df09d9adede5bfc40ff1a39a3a17fc8e29f15c56f16b7e48680c600ee5ac" - contract = create :contract, code_hash: code_hash, hash_type: hash_type - block = create :block, :with_block_hash - ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: block) - CkbTransaction.where('id > ?', ckb_transaction.id).delete_all - script = create :script - type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id - lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id - cell_output = create :cell_output, :with_full_transaction, block_id: block.id - cell_output.update lock_script_id: lock_script.id, type_script_id: type_script.id, ckb_transaction_id: ckb_transaction.id - - # for the 1st time, it will create - ScriptTransaction.create_initial_data - @script_transaction = ScriptTransaction.first - assert_equal 1, ScriptTransaction.all.count - assert_equal ckb_transaction.id, @script_transaction.ckb_transaction_id - assert_equal script.id, @script_transaction.script_id - - # for the 2nd time, it should NOT create new record - ScriptTransaction.create_initial_data - assert_equal 1, ScriptTransaction.all.count - end - -end +# class ScriptTransactionTest < ActiveSupport::TestCase +# setup do +# @contract = create :contract +# @block = create(:block, :with_block_hash) +# @script = create :script, contract_id: @contract.id +# @ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: @block) +# @script_transaction = create :script_transaction, script_id: @script.id, ckb_transaction_id: @ckb_transaction.id +# end + +# context "associations" do +# should belong_to(:script) +# should belong_to(:ckb_transaction) +# end + +# test "it should create script_transaction" do +# assert_equal @ckb_transaction.id, @script_transaction.ckb_transaction_id +# assert_equal @script.id, @script_transaction.script_id +# end + +# test "it should update script_transaction" do +# @script_transaction.update ckb_transaction_id: @ckb_transaction.id - 1, script_id: @script.id - 1 +# assert_equal @ckb_transaction.id - 1, @script_transaction.ckb_transaction_id +# assert_equal @script.id - 1, @script_transaction.script_id +# end + +# test "it should create_initial_data" do +# TypeScript.delete_all +# LockScript.delete_all +# Script.delete_all +# ScriptTransaction.delete_all +# Block.delete_all +# Contract.delete_all +# CellOutput.delete_all + +# hash_type = 'type' +# code_hash = "0x1c04df09d9adede5bfc40ff1a39a3a17fc8e29f15c56f16b7e48680c600ee5ac" +# contract = create :contract, code_hash: code_hash, hash_type: hash_type +# block = create :block, :with_block_hash +# ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: block) +# CkbTransaction.where('id > ?', ckb_transaction.id).delete_all +# script = create :script +# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id +# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id +# cell_output = create :cell_output, :with_full_transaction, block_id: block.id +# cell_output.update lock_script_id: lock_script.id, type_script_id: type_script.id, ckb_transaction_id: ckb_transaction.id + +# # for the 1st time, it will create +# ScriptTransaction.create_initial_data +# @script_transaction = ScriptTransaction.first +# assert_equal 1, ScriptTransaction.all.count +# assert_equal ckb_transaction.id, @script_transaction.ckb_transaction_id +# assert_equal script.id, @script_transaction.script_id + +# # for the 2nd time, it should NOT create new record +# ScriptTransaction.create_initial_data +# assert_equal 1, ScriptTransaction.all.count +# end + +# end diff --git a/vcr_fixtures/vcr_cassettes/blocks/33.yml b/vcr_fixtures/vcr_cassettes/blocks/33.yml index d5f9c3b4e..3613e221e 100644 --- a/vcr_fixtures/vcr_cassettes/blocks/33.yml +++ b/vcr_fixtures/vcr_cassettes/blocks/33.yml @@ -1,39 +1,40 @@ --- http_interactions: -- request: - method: post - uri: http://localhost:8114/ - body: - encoding: UTF-8 - string: '{"id":1,"jsonrpc":"2.0","method":"get_block_by_number","params":["0x21","0x2",false]}' - headers: - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - Accept: - - "*/*" - User-Agent: - - Ruby - Content-Type: - - application/json - Connection: - - keep-alive - Keep-Alive: - - '30' - response: - status: - code: 200 - message: OK - headers: - Content-Type: - - application/json; charset=utf-8 - Content-Length: - - '2138' - Date: - - Fri, 04 Oct 2019 15:54:13 GMT - body: - encoding: UTF-8 - string: '{"jsonrpc":"2.0","result":{"extension":"0xa33703945490c0d8eb61dd564dcdce04d6ad80a8ae1aeef671354f9735ec74bb","header":{"compact_target":"0x1d08cdb1","dao":"0x4462198b0e5d5c4aad67c38868c82700749fdc3d3514d80500ec69f6012acf08","epoch":"0x70803ee001ed5","extra_hash":"0x7f28e2900ffc36be0bcbe76253ec558d5c2ce1868ba029438d7a39f514078056","hash":"0x1dcad92e8085f70ed8dc7eb3c105dbae84bd267f4f426cf265f9d959436a1287","nonce":"0x6691cc8bd17283f67f35b2bdf31fad91","number":"0x21","parent_hash":"0x96f44bbc683837c917066f7b610a6709b629604bb4a544293f45e522ae57e4b3","proposals_hash":"0x297d92aff8d62ba05f067085afe1082bc8b080883f27cfcd440be1bea1a5433e","timestamp":"0x18cba8806b7","transactions_root":"0x171dbdcf5572615f2c111f9fd3eef00304f25f482b0f1bf141bb7b742769a136","version":"0x0"},"proposals":["0xe7989e121502a9c906d1","0xb31087bf0881f23574b0"],"transactions":[{"cell_deps":[],"hash":"0xe150a92d7a15f9f85bc0fd806885b012b1c084728ef6c0f1af157fad59814f3c","header_deps":[],"inputs":[{"previous_output":{"index":"0xffffffff","tx_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"since":"0xb3bf47"}],"outputs":[{"capacity":"0x19bf50f9db","lock":{"args":"0x0450340178ae277261a838c89f9ccb76a190ed4b","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x"],"version":"0x0","witnesses":["0x830000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce80114000000da648442dbb7347e467d1d09da13e5cd3a0ef0e12a0000000000000020302e3131332e302d72633220283866663030323620323032332d31322d31392920deadbeef"]},{"cell_deps":[{"dep_type":"dep_group","out_point":{"index":"0x0","tx_hash":"0x4dcf3f3b09efac8995d6cbee87c5345e812d310094651e0c3d9a730f32dc9263"}},{"dep_type":"code","out_point":{"index":"0x0","tx_hash":"0x7bf3899cf41879ed0319bf5312c9db5bf5620fff9ebe59556c261c48f0369054"}}],"hash":"0x7046d8c5641f0cfa22bf4b2905bd4fb0e619e42bc008130a8dc743d2959fef3b","header_deps":[],"inputs":[{"previous_output":{"index":"0x1","tx_hash":"0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4"},"since":"0x0"}],"outputs":[{"capacity":"0x525430e20","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":{"args":"0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d","code_hash":"0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6","hash_type":"type"}}],"outputs_data":["0x0814434b42204669737420496e736372697074696f6e04434b4249a69f54bf339dd121febe64cb0be3a2cf366a8b13ec1a5ae4bebdccb9039c7efa0040075af0750700000000000000000000e8764817000000000000000000000002"],"version":"0x0","witnesses":["0x6b010000100000006b0100006b01000057010000014599a5795423d54ab8e1f44f5c6ef5be9b1829beddb787bc732e4469d25f8c93e94afa393617f905bf1765c35dc38501a862b4b2f794a88b4f9010da02411a85e201947f9c04ff5ca1b92412f11a28d74c48339e48a192d8327738515469a877475fcd3b47c81e7d026d30b853e12bb250779a999f0aba1057e9add098f713f749960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630162f9fb777b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22596a56694d7a45325a6d5a694e4749774d3259314e474d795a6d51355a445978595756694f5745774f5455334f444a6b5a6d526a5a544a6c4d545a6d5a4755315a6a45345a4759314d4451354f4459355a6a45785967222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a38303030222c2263726f73734f726967696e223a66616c73657d"]}],"uncles":[]},"id":2} - ' - http_version: - recorded_at: Fri, 04 Oct 2019 15:54:13 GMT + - request: + method: post + uri: http://localhost:8114/ + body: + encoding: UTF-8 + string: '{"id":1,"jsonrpc":"2.0","method":"get_block_by_number","params":["0x21","0x2",false]}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/json + Connection: + - keep-alive + Keep-Alive: + - "30" + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - "2138" + Date: + - Fri, 04 Oct 2019 15:54:13 GMT + body: + encoding: UTF-8 + string: + '{"jsonrpc":"2.0","result":{"extension":"0xa33703945490c0d8eb61dd564dcdce04d6ad80a8ae1aeef671354f9735ec74bb","header":{"compact_target":"0x1d08cdb1","dao":"0x4462198b0e5d5c4aad67c38868c82700749fdc3d3514d80500ec69f6012acf08","epoch":"0x70803ee001ed5","extra_hash":"0x7f28e2900ffc36be0bcbe76253ec558d5c2ce1868ba029438d7a39f514078056","hash":"0x1dcad92e8085f70ed8dc7eb3c105dbae84bd267f4f426cf265f9d959436a1287","nonce":"0x6691cc8bd17283f67f35b2bdf31fad91","number":"0x21","parent_hash":"0x96f44bbc683837c917066f7b610a6709b629604bb4a544293f45e522ae57e4b3","proposals_hash":"0x297d92aff8d62ba05f067085afe1082bc8b080883f27cfcd440be1bea1a5433e","timestamp":"0x18cba8806b7","transactions_root":"0x171dbdcf5572615f2c111f9fd3eef00304f25f482b0f1bf141bb7b742769a136","version":"0x0"},"proposals":["0xe7989e121502a9c906d1","0xb31087bf0881f23574b0"],"transactions":[{"cell_deps":[],"hash":"0xe150a92d7a15f9f85bc0fd806885b012b1c084728ef6c0f1af157fad59814f3c","header_deps":[],"inputs":[{"previous_output":{"index":"0xffffffff","tx_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"since":"0xb3bf47"}],"outputs":[{"capacity":"0x19bf50f9db","lock":{"args":"0x0450340178ae277261a838c89f9ccb76a190ed4b","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x"],"version":"0x0","witnesses":["0x830000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce80114000000da648442dbb7347e467d1d09da13e5cd3a0ef0e12a0000000000000020302e3131332e302d72633220283866663030323620323032332d31322d31392920deadbeef"]},{"cell_deps":[],"hash":"0x7046d8c5641f0cfa22bf4b2905bd4fb0e619e42bc008130a8dc743d2959fef3b","header_deps":[],"inputs":[{"previous_output":{"index":"0x1","tx_hash":"0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4"},"since":"0x0"}],"outputs":[{"capacity":"0x525430e20","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":{"args":"0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d","code_hash":"0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6","hash_type":"type"}}],"outputs_data":["0x0814434b42204669737420496e736372697074696f6e04434b4249a69f54bf339dd121febe64cb0be3a2cf366a8b13ec1a5ae4bebdccb9039c7efa0040075af0750700000000000000000000e8764817000000000000000000000002"],"version":"0x0","witnesses":["0x6b010000100000006b0100006b01000057010000014599a5795423d54ab8e1f44f5c6ef5be9b1829beddb787bc732e4469d25f8c93e94afa393617f905bf1765c35dc38501a862b4b2f794a88b4f9010da02411a85e201947f9c04ff5ca1b92412f11a28d74c48339e48a192d8327738515469a877475fcd3b47c81e7d026d30b853e12bb250779a999f0aba1057e9add098f713f749960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630162f9fb777b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22596a56694d7a45325a6d5a694e4749774d3259314e474d795a6d51355a445978595756694f5745774f5455334f444a6b5a6d526a5a544a6c4d545a6d5a4755315a6a45345a4759314d4451354f4459355a6a45785967222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a38303030222c2263726f73734f726967696e223a66616c73657d"]}],"uncles":[]},"id":2} + ' + http_version: + recorded_at: Fri, 04 Oct 2019 15:54:13 GMT recorded_with: VCR 5.0.0 From 495503bf8f7b3ac61b380f4b5b4e5540f4e9b202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:38:35 +0900 Subject: [PATCH 03/11] chore(deps): bump rails-html-sanitizer from 1.6.0 to 1.6.1 (#2305) Bumps [rails-html-sanitizer](https://github.com/rails/rails-html-sanitizer) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/rails/rails-html-sanitizer/releases) - [Changelog](https://github.com/rails/rails-html-sanitizer/blob/main/CHANGELOG.md) - [Commits](https://github.com/rails/rails-html-sanitizer/compare/v1.6.0...v1.6.1) --- updated-dependencies: - dependency-name: rails-html-sanitizer dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b59939032..c7c4b930e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -273,7 +273,7 @@ GEM llhttp-ffi (0.4.0) ffi-compiler (~> 1.0) rake (~> 13.0) - loofah (2.22.0) + loofah (2.23.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -284,7 +284,7 @@ GEM marcel (1.0.4) method_source (1.1.0) mini_mime (1.1.5) - mini_portile2 (2.8.7) + mini_portile2 (2.8.8) minitest (5.25.1) minitest-reporters (1.6.1) ansi @@ -308,12 +308,12 @@ GEM net-protocol newrelic_rpm (8.12.0) nio4r (2.7.3) - nokogiri (1.16.7) + nokogiri (1.16.8) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.16.7-arm64-darwin) + nokogiri (1.16.8-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.7-x86_64-linux) + nokogiri (1.16.8-x86_64-linux) racc (~> 1.4) pagy (5.10.1) activesupport @@ -375,9 +375,9 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.1) loofah (~> 2.21) - nokogiri (~> 1.14) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) railties (7.0.8.5) actionpack (= 7.0.8.5) activesupport (= 7.0.8.5) From 6c9ce5cce1fa628649eeb57a5538804b4efb3845 Mon Sep 17 00:00:00 2001 From: Rabbit Date: Thu, 5 Dec 2024 16:00:40 +0800 Subject: [PATCH 04/11] Feat/fiber (#2301) * feat: synchronize peer and channel data in fiber network * feat: add fiber coordinator * chore: add foreign key fiber_peer_id * chore: rename sent_tlc_balance column * chore: refine fiber channel jbuilder attribute definitions * feat: fiber peers paginate * chore: change rpc_listening_addr type to array * feat: sync fiber graph nodes and channels * fix: set default page_size for fiber request * feat: sync graph node udt config info * chore: fiber udt cfg info add type_script * refactor: fiber graph detect worker * chore: add filter to fiber graph channels * feat: add filter query to fiber graph node * refactor: normalize query_key based on hex string detection * feat: fiber graph channel add closed_transaction_info --- .env.example | 3 + .../api/v2/fiber/channels_controller.rb | 12 + .../api/v2/fiber/graph_channels_controller.rb | 17 + .../api/v2/fiber/graph_nodes_controller.rb | 31 ++ .../api/v2/fiber/peers_controller.rb | 46 ++ .../api/v2/portfolio/addresses_controller.rb | 2 +- app/lib/api/v2/exceptions.rb | 30 +- app/models/fiber_channel.rb | 35 ++ app/models/fiber_graph_channel.rb | 75 +++ app/models/fiber_graph_node.rb | 50 ++ app/models/fiber_peer.rb | 38 ++ app/models/fiber_transaction.rb | 16 + app/models/fiber_udt_cfg_info.rb | 24 + app/models/referring_cell.rb | 1 + app/models/suggest_query.rb | 14 + app/serializers/fiber_channel_serializer.rb | 7 + .../fiber_graph_node_serializer.rb | 6 + app/services/fiber_coordinator.rb | 41 ++ app/views/api/v2/fiber/channels/show.jbuilder | 11 + .../v2/fiber/graph_channels/index.jbuilder | 17 + .../api/v2/fiber/graph_nodes/index.jbuilder | 13 + .../api/v2/fiber/graph_nodes/show.jbuilder | 18 + app/views/api/v2/fiber/peers/index.jbuilder | 10 + app/views/api/v2/fiber/peers/show.jbuilder | 9 + app/workers/fiber_detect_worker.rb | 49 ++ app/workers/fiber_graph_detect_worker.rb | 122 +++++ config/routes/v2.rb | 6 + config/settings.mainnet.yml | 3 + config/settings.testnet.yml | 3 + config/sidekiq.yml | 1 + .../20240918024407_create_fiber_peers.rb | 13 + .../20240918024415_create_fiber_channels.rb | 19 + ...0240918033146_create_fiber_transactions.rb | 11 + ...807_add_fiber_peer_id_to_fiber_channels.rb | 7 + ...5539_update_rpc_listening_addr_to_array.rb | 5 + ...20241012014906_create_fiber_graph_infos.rb | 33 ++ ...241023055256_create_fiber_udt_cfg_infos.rb | 13 + ...3536_add_udt_id_to_fiber_graph_channels.rb | 5 + ..._transaction_id_to_fiber_graph_channels.rb | 8 + ...032447_add_peer_id_to_fiber_graph_nodes.rb | 5 + db/structure.sql | 478 ++++++++++++++++-- lib/scheduler.rb | 4 + test/factories/fiber_channels.rb | 5 + test/factories/fiber_graph_channels.rb | 5 + test/factories/fiber_graph_nodes.rb | 5 + test/factories/fiber_peers.rb | 5 + test/factories/fiber_udt_cfg_infos.rb | 5 + test/models/fiber_channel_test.rb | 7 + test/models/fiber_graph_channel_test.rb | 7 + test/models/fiber_graph_node_test.rb | 7 + test/models/fiber_peer_test.rb | 7 + test/models/fiber_udt_cfg_info_test.rb | 7 + 52 files changed, 1334 insertions(+), 37 deletions(-) create mode 100644 app/controllers/api/v2/fiber/channels_controller.rb create mode 100644 app/controllers/api/v2/fiber/graph_channels_controller.rb create mode 100644 app/controllers/api/v2/fiber/graph_nodes_controller.rb create mode 100644 app/controllers/api/v2/fiber/peers_controller.rb create mode 100644 app/models/fiber_channel.rb create mode 100644 app/models/fiber_graph_channel.rb create mode 100644 app/models/fiber_graph_node.rb create mode 100644 app/models/fiber_peer.rb create mode 100644 app/models/fiber_transaction.rb create mode 100644 app/models/fiber_udt_cfg_info.rb create mode 100644 app/serializers/fiber_channel_serializer.rb create mode 100644 app/serializers/fiber_graph_node_serializer.rb create mode 100644 app/services/fiber_coordinator.rb create mode 100644 app/views/api/v2/fiber/channels/show.jbuilder create mode 100644 app/views/api/v2/fiber/graph_channels/index.jbuilder create mode 100644 app/views/api/v2/fiber/graph_nodes/index.jbuilder create mode 100644 app/views/api/v2/fiber/graph_nodes/show.jbuilder create mode 100644 app/views/api/v2/fiber/peers/index.jbuilder create mode 100644 app/views/api/v2/fiber/peers/show.jbuilder create mode 100644 app/workers/fiber_detect_worker.rb create mode 100644 app/workers/fiber_graph_detect_worker.rb create mode 100644 db/migrate/20240918024407_create_fiber_peers.rb create mode 100644 db/migrate/20240918024415_create_fiber_channels.rb create mode 100644 db/migrate/20240918033146_create_fiber_transactions.rb create mode 100644 db/migrate/20240920094807_add_fiber_peer_id_to_fiber_channels.rb create mode 100644 db/migrate/20240924065539_update_rpc_listening_addr_to_array.rb create mode 100644 db/migrate/20241012014906_create_fiber_graph_infos.rb create mode 100644 db/migrate/20241023055256_create_fiber_udt_cfg_infos.rb create mode 100644 db/migrate/20241023063536_add_udt_id_to_fiber_graph_channels.rb create mode 100644 db/migrate/20241030023309_add_transaction_id_to_fiber_graph_channels.rb create mode 100644 db/migrate/20241129032447_add_peer_id_to_fiber_graph_nodes.rb create mode 100644 test/factories/fiber_channels.rb create mode 100644 test/factories/fiber_graph_channels.rb create mode 100644 test/factories/fiber_graph_nodes.rb create mode 100644 test/factories/fiber_peers.rb create mode 100644 test/factories/fiber_udt_cfg_infos.rb create mode 100644 test/models/fiber_channel_test.rb create mode 100644 test/models/fiber_graph_channel_test.rb create mode 100644 test/models/fiber_graph_node_test.rb create mode 100644 test/models/fiber_peer_test.rb create mode 100644 test/models/fiber_udt_cfg_info_test.rb diff --git a/.env.example b/.env.example index fe6ed13b7..a468ee942 100644 --- a/.env.example +++ b/.env.example @@ -127,3 +127,6 @@ BITCOIN_SIGNET_PASS="" # Dynamic CORS configuration PARTNER_DOMAINS="/localhost:\d*/" + +# -------------------------------- Fiber segment -------------------------------- +FIBER_NODE_URL="" \ No newline at end of file diff --git a/app/controllers/api/v2/fiber/channels_controller.rb b/app/controllers/api/v2/fiber/channels_controller.rb new file mode 100644 index 000000000..bb21847dc --- /dev/null +++ b/app/controllers/api/v2/fiber/channels_controller.rb @@ -0,0 +1,12 @@ +module Api + module V2 + module Fiber + class ChannelsController < BaseController + def show + @channel = FiberChannel.find_by(channel_id: params[:channel_id]) + raise Api::V2::Exceptions::FiberChannelNotFoundError unless @channel + end + end + end + end +end diff --git a/app/controllers/api/v2/fiber/graph_channels_controller.rb b/app/controllers/api/v2/fiber/graph_channels_controller.rb new file mode 100644 index 000000000..59fee4c0b --- /dev/null +++ b/app/controllers/api/v2/fiber/graph_channels_controller.rb @@ -0,0 +1,17 @@ +module Api + module V2 + module Fiber + class GraphChannelsController < BaseController + def index + @page = params.fetch(:page, 1) + @page_size = params.fetch(:page_size, FiberPeer.default_per_page) + @channels = FiberGraphChannel.all + if params[:status] == "closed" + @channels = @channels.where.not(closed_transaction_id: nil) + end + @channels = @channels.page(@page).per(@page_size) + end + end + end + end +end diff --git a/app/controllers/api/v2/fiber/graph_nodes_controller.rb b/app/controllers/api/v2/fiber/graph_nodes_controller.rb new file mode 100644 index 000000000..2c175c037 --- /dev/null +++ b/app/controllers/api/v2/fiber/graph_nodes_controller.rb @@ -0,0 +1,31 @@ +module Api + module V2 + module Fiber + class GraphNodesController < BaseController + def index + @page = params.fetch(:page, 1) + @page_size = params.fetch(:page_size, FiberGraphNode.default_per_page) + @nodes = + if params[:q].present? + FiberGraphNode.where("alias = :q or peer_id = :q or node_id = :q", q: params[:q]).page(@page).per(@page_size) + else + FiberGraphNode.all.page(@page).per(@page_size) + end + end + + def show + @node = FiberGraphNode.find_by(node_id: params[:node_id]) + raise Api::V2::Exceptions::FiberGraphNodeNotFoundError unless @node + + @graph_channels = FiberGraphChannel.where(node1: params[:node_id]).or( + FiberGraphChannel.where(node2: params[:node_id]), + ) + + if params[:status] == "closed" + @graph_channels = @graph_channels.where.not(closed_transaction_id: nil) + end + end + end + end + end +end diff --git a/app/controllers/api/v2/fiber/peers_controller.rb b/app/controllers/api/v2/fiber/peers_controller.rb new file mode 100644 index 000000000..fb1584b01 --- /dev/null +++ b/app/controllers/api/v2/fiber/peers_controller.rb @@ -0,0 +1,46 @@ +module Api + module V2 + module Fiber + class PeersController < BaseController + before_action :test_connection, only: :create + + def index + @page = params.fetch(:page, 1) + @page_size = params.fetch(:page_size, FiberPeer.default_per_page) + @peers = FiberPeer.all.page(@page).per(@page_size) + end + + def show + @peer = FiberPeer.find_by(peer_id: params[:peer_id]) + raise Api::V2::Exceptions::FiberPeerNotFoundError unless @peer + end + + def create + fiber_peer = FiberPeer.find_or_initialize_by(peer_id: fiber_peer_params[:peer_id]) + fiber_peer.name = fiber_peer_params[:name] + new_rpc = Array(fiber_peer_params[:rpc_listening_addr]) + fiber_peer.rpc_listening_addr = (fiber_peer.rpc_listening_addr + new_rpc).uniq + fiber_peer.save! + + FiberDetectWorker.perform_async(fiber_peer.peer_id) + + head :no_content + rescue ActiveRecord::RecordInvalid => e + raise Api::V2::Exceptions::FiberPeerParamsInvalidError.new(e.message) + end + + private + + def fiber_peer_params + params.permit(:name, :peer_id, :rpc_listening_addr) + end + + def test_connection + FiberCoordinator.instance.list_channels(fiber_peer_params[:rpc_listening_addr], { "peer_id": nil }) + rescue StandardError => e + raise Api::V2::Exceptions::FiberPeerParamsInvalidError.new(e.message) + end + end + end + end +end diff --git a/app/controllers/api/v2/portfolio/addresses_controller.rb b/app/controllers/api/v2/portfolio/addresses_controller.rb index 3925d326b..37d5b20fd 100644 --- a/app/controllers/api/v2/portfolio/addresses_controller.rb +++ b/app/controllers/api/v2/portfolio/addresses_controller.rb @@ -10,7 +10,7 @@ def create head :no_content rescue StandardError => e - raise Api::V2::Exceptions::SyncPortfolioAddressesError + raise Api::V2::Exceptions::ParamsInvalidError end end end diff --git a/app/lib/api/v2/exceptions.rb b/app/lib/api/v2/exceptions.rb index 857785075..c33080b83 100644 --- a/app/lib/api/v2/exceptions.rb +++ b/app/lib/api/v2/exceptions.rb @@ -21,13 +21,13 @@ def initialize(detail) class TokenCollectionNotFoundError < Error def initialize - super(code: 2001, status: 404, title: "Token Collection Not Found", detail: "No token collection found by given script hash or id", href: "") + super(code: 2001, status: 404, title: "token collection not found", detail: "No token collection found by given script hash or id", href: "") end end class AddressNotMatchEnvironmentError < Error def initialize(ckb_net_mode) - super(code: 2022, status: 422, title: "Address is invalid", detail: "This address is not the #{ckb_net_mode} address", href: "") + super(code: 2022, status: 422, title: "address is invalid", detail: "This address is not the #{ckb_net_mode} address", href: "") end end @@ -69,7 +69,31 @@ def initialize class AddressNotFoundError < Error def initialize - super code: 2009, status: 404, title: "Address Not Found", detail: "No address found by given address hash or lock hash", href: "" + super code: 2009, status: 404, title: "address not found", detail: "No address found by given address hash or lock hash", href: "" + end + end + + class FiberPeerParamsInvalidError < Error + def initialize(detail) + super code: 2010, status: 404, title: "fiber peer params invalid", detail: , href: "" + end + end + + class FiberPeerNotFoundError < Error + def initialize + super code: 2011, status: 404, title: "fiber peer not found", detail: "No peer found by given peer id", href: "" + end + end + + class FiberChannelNotFoundError < Error + def initialize + super code: 2012, status: 404, title: "fiber channel not found", detail: "No channel found by given channel_id", href: "" + end + end + + class FiberGraphNodeNotFoundError < Error + def initialize + super code: 2013, status: 404, title: "fiber graph node not found", detail: "No graph node found by given node id", href: "" end end end diff --git a/app/models/fiber_channel.rb b/app/models/fiber_channel.rb new file mode 100644 index 000000000..6c6d98c3c --- /dev/null +++ b/app/models/fiber_channel.rb @@ -0,0 +1,35 @@ +class FiberChannel < ApplicationRecord + belongs_to :fiber_peer + + def local_peer + fiber_peer || FiberPeer.new + end + + def remote_peer + FiberPeer.find_by(peer_id:) || FiberPeer.new + end +end + +# == Schema Information +# +# Table name: fiber_channels +# +# id :bigint not null, primary key +# peer_id :string +# channel_id :string +# state_name :string +# state_flags :string default([]), is an Array +# local_balance :decimal(64, 2) default(0.0) +# offered_tlc_balance :decimal(64, 2) default(0.0) +# remote_balance :decimal(64, 2) default(0.0) +# received_tlc_balance :decimal(64, 2) default(0.0) +# shutdown_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# fiber_peer_id :integer +# +# Indexes +# +# index_fiber_channels_on_fiber_peer_id (fiber_peer_id) +# index_fiber_channels_on_peer_id_and_channel_id (peer_id,channel_id) UNIQUE +# diff --git a/app/models/fiber_graph_channel.rb b/app/models/fiber_graph_channel.rb new file mode 100644 index 000000000..42e03ee64 --- /dev/null +++ b/app/models/fiber_graph_channel.rb @@ -0,0 +1,75 @@ +class FiberGraphChannel < ApplicationRecord + MAX_PAGINATES_PER = 100 + DEFAULT_PAGINATES_PER = 10 + paginates_per DEFAULT_PAGINATES_PER + max_paginates_per MAX_PAGINATES_PER + + belongs_to :udt, optional: true + belongs_to :open_transaction, class_name: "CkbTransaction" + belongs_to :closed_transaction, class_name: "CkbTransaction", optional: true + + validates :open_transaction_id, presence: true + + scope :open_channels, -> { where(closed_transaction_id: nil) } + + def open_transaction_info + open_transaction.as_json(only: %i[tx_hash block_number block_timestamp]).merge( + { + capacity: funding_cell.capacity, + udt_amount: funding_cell.udt_amount, + address: funding_cell.address_hash, + }, + ) + end + + def closed_transaction_info + return Hash.new unless closed_transaction + + closed_transaction.as_json(only: %i[tx_hash block_number block_timestamp]).merge( + close_accounts: closed_transaction.outputs.map do |cell| + { + capacity: cell.capacity, + udt_amount: cell.udt_amount, + address: cell.address_hash, + } + end, + ) + end + + def udt_info + udt&.as_json(only: %i[full_name symbol decimal icon_file]) + end + + def funding_cell + open_transaction.outputs.includes(:lock_script).find_by( + lock_scripts: { code_hash: Settings.fiber_funding_code_hash }, + ) + end +end + +# == Schema Information +# +# Table name: fiber_graph_channels +# +# id :bigint not null, primary key +# channel_outpoint :string +# funding_tx_block_number :bigint +# funding_tx_index :integer +# node1 :string +# node2 :string +# last_updated_timestamp :bigint +# created_timestamp :bigint +# node1_to_node2_fee_rate :decimal(30, ) default(0) +# node2_to_node1_fee_rate :decimal(30, ) default(0) +# capacity :decimal(64, 2) default(0.0) +# chain_hash :string +# created_at :datetime not null +# updated_at :datetime not null +# udt_id :bigint +# open_transaction_id :bigint +# closed_transaction_id :bigint +# +# Indexes +# +# index_fiber_graph_channels_on_channel_outpoint (channel_outpoint) UNIQUE +# diff --git a/app/models/fiber_graph_node.rb b/app/models/fiber_graph_node.rb new file mode 100644 index 000000000..4b39f8496 --- /dev/null +++ b/app/models/fiber_graph_node.rb @@ -0,0 +1,50 @@ +class FiberGraphNode < ApplicationRecord + MAX_PAGINATES_PER = 100 + DEFAULT_PAGINATES_PER = 10 + paginates_per DEFAULT_PAGINATES_PER + max_paginates_per MAX_PAGINATES_PER + + has_many :fiber_udt_cfg_infos, dependent: :delete_all + + def channel_links + FiberGraphChannel.where(node1: node_id).or(FiberGraphChannel.where(node2: node_id)). + where(closed_transaction_id: nil) + end + + def udt_cfg_infos + fiber_udt_cfg_infos.map(&:udt_info) + end + + def total_capacity + channel_links.sum(&:capacity) + end + + def connected_node_ids + node_ids = channel_links.pluck(:node1, :node2).flatten + node_ids.uniq - [node_id] + end + + def open_channels_count + channel_links.count + end +end + +# == Schema Information +# +# Table name: fiber_graph_nodes +# +# id :bigint not null, primary key +# alias :string +# node_id :string +# addresses :string default([]), is an Array +# timestamp :bigint +# chain_hash :string +# auto_accept_min_ckb_funding_amount :decimal(30, ) +# created_at :datetime not null +# updated_at :datetime not null +# peer_id :string +# +# Indexes +# +# index_fiber_graph_nodes_on_node_id (node_id) UNIQUE +# diff --git a/app/models/fiber_peer.rb b/app/models/fiber_peer.rb new file mode 100644 index 000000000..616e3c1d0 --- /dev/null +++ b/app/models/fiber_peer.rb @@ -0,0 +1,38 @@ +class FiberPeer < ApplicationRecord + MAX_PAGINATES_PER = 100 + DEFAULT_PAGINATES_PER = 10 + paginates_per DEFAULT_PAGINATES_PER + max_paginates_per MAX_PAGINATES_PER + + has_many :fiber_channels, dependent: :destroy + + validates :peer_id, presence: true, uniqueness: true + + def total_local_balance + fiber_channels.where(state_name: "CHANNEL_READY").sum(:local_balance) + end + + def channels_count + fiber_channels.where(state_name: "CHANNEL_READY").count + end +end + +# == Schema Information +# +# Table name: fiber_peers +# +# id :bigint not null, primary key +# name :string +# peer_id :string +# rpc_listening_addr :string default([]), is an Array +# first_channel_opened_at :datetime +# last_channel_updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# node_id :string +# chain_hash :string +# +# Indexes +# +# index_fiber_peers_on_peer_id (peer_id) UNIQUE +# diff --git a/app/models/fiber_transaction.rb b/app/models/fiber_transaction.rb new file mode 100644 index 000000000..4660675df --- /dev/null +++ b/app/models/fiber_transaction.rb @@ -0,0 +1,16 @@ +class FiberTransaction < ApplicationRecord + belongs_to :fiber_channel + belongs_to :fiber_peer +end + +# == Schema Information +# +# Table name: fiber_transactions +# +# id :bigint not null, primary key +# fiber_peer_id :integer +# fiber_channel_id :integer +# ckb_transaction_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# diff --git a/app/models/fiber_udt_cfg_info.rb b/app/models/fiber_udt_cfg_info.rb new file mode 100644 index 000000000..fb5d9b8d6 --- /dev/null +++ b/app/models/fiber_udt_cfg_info.rb @@ -0,0 +1,24 @@ +class FiberUdtCfgInfo < ApplicationRecord + belongs_to :fiber_graph_node + belongs_to :udt + + def udt_info + udt.as_json(only: %i[full_name symbol decimal icon_file args code_hash hash_type]).merge(auto_accept_amount:) + end +end + +# == Schema Information +# +# Table name: fiber_udt_cfg_infos +# +# id :bigint not null, primary key +# fiber_graph_node_id :bigint +# udt_id :bigint +# auto_accept_amount :decimal(64, 2) default(0.0) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_fiber_udt_cfg_infos_on_fiber_graph_node_id_and_udt_id (fiber_graph_node_id,udt_id) UNIQUE +# diff --git a/app/models/referring_cell.rb b/app/models/referring_cell.rb index 9ae25ebf2..2deaba7d1 100644 --- a/app/models/referring_cell.rb +++ b/app/models/referring_cell.rb @@ -56,5 +56,6 @@ def self.create_initial_data_for_ckb_transaction(ckb_transaction) # # Indexes # +# index_referring_cells_on_cell_output_id (cell_output_id) UNIQUE # index_referring_cells_on_contract_id_and_cell_output_id (contract_id,cell_output_id) UNIQUE # diff --git a/app/models/suggest_query.rb b/app/models/suggest_query.rb index e61740cda..b004e963f 100644 --- a/app/models/suggest_query.rb +++ b/app/models/suggest_query.rb @@ -57,6 +57,9 @@ def aggregate_query! if (collections = find_nft_collections_by_name).present? results[:data].concat(collections.serializable_hash[:data]) end + if (nodes = find_fiber_graph_nodes).present? + results[:data].concat(nodes.serializable_hash[:data]) + end raise ActiveRecord::RecordNotFound if results.blank? @@ -152,4 +155,15 @@ def find_bitcoin_address bitcoin_address = BitcoinAddress.find_by(address_hash: query_key) BitcoinAddressSerializer.new(bitcoin_address) if bitcoin_address.present? end + + def find_fiber_graph_nodes + normalized_key = + if QueryKeyUtils.start_with_default_hash_prefix?(query_key) + query_key.delete_prefix(Settings.default_hash_prefix) + else + query_key + end + fiber_graph_nodes = FiberGraphNode.where("alias = :query_key or peer_id = :query_key or node_id = :query_key", query_key: normalized_key) + FiberGraphNodeSerializer.new(fiber_graph_nodes) if fiber_graph_nodes.present? + end end diff --git a/app/serializers/fiber_channel_serializer.rb b/app/serializers/fiber_channel_serializer.rb new file mode 100644 index 000000000..2262ef5a6 --- /dev/null +++ b/app/serializers/fiber_channel_serializer.rb @@ -0,0 +1,7 @@ +class FiberChannelSerializer + include FastJsonapi::ObjectSerializer + + attributes :peer_id, :channel_id, :state_name, :state_flags, :local_balance, + :sent_tlc_balance, :remote_balance, :received_tlc_balance, :shutdown_at, + :created_at, :updated_at +end diff --git a/app/serializers/fiber_graph_node_serializer.rb b/app/serializers/fiber_graph_node_serializer.rb new file mode 100644 index 000000000..a191d52ee --- /dev/null +++ b/app/serializers/fiber_graph_node_serializer.rb @@ -0,0 +1,6 @@ +class FiberGraphNodeSerializer + include FastJsonapi::ObjectSerializer + + attributes :id, :alias, :node_id, :peer_id, :addresses, :timestamp, :chain_hash, + :auto_accept_min_ckb_funding_amount +end diff --git a/app/services/fiber_coordinator.rb b/app/services/fiber_coordinator.rb new file mode 100644 index 000000000..a8f143a9a --- /dev/null +++ b/app/services/fiber_coordinator.rb @@ -0,0 +1,41 @@ +class FiberCoordinator + include Singleton + METHOD_NAMES = %w(graph_nodes graph_channels list_channels).freeze + + def initialize + @id = 0 + end + + METHOD_NAMES.each do |name| + define_method name do |endpoint, *params| + call_rpc(name, endpoint, params:) + end + end + + private + + def call_rpc(method, endpoint, params: []) + @id += 1 + payload = { jsonrpc: "2.0", id: @id, method:, params: } + make_request(endpoint, payload) + end + + def make_request(endpoint, payload) + response = HTTP.timeout(60).post(endpoint, json: payload) + parse_response(response) + end + + def parse_response(response) + data = JSON.parse(response.to_s) + + return data if data.is_a?(Array) + + if data.is_a?(Hash) + raise ArgumentError, data["error"]["data"] if data["error"].present? + else + raise ArgumentError, "Unexpected response format: #{data.class}" + end + + data + end +end diff --git a/app/views/api/v2/fiber/channels/show.jbuilder b/app/views/api/v2/fiber/channels/show.jbuilder new file mode 100644 index 000000000..570f174f0 --- /dev/null +++ b/app/views/api/v2/fiber/channels/show.jbuilder @@ -0,0 +1,11 @@ +json.data do + json.(@channel, :channel_id, :state_name, :state_flags, :shutdown_at, :created_at, :updated_at, :local_balance, :offered_tlc_balance, :remote_balance, :received_tlc_balance) + + json.local_peer do + json.(@channel.local_peer, :peer_id, :name, :rpc_listening_addr) + end + + json.remote_peer do + json.(@channel.remote_peer, :peer_id, :name, :rpc_listening_addr) + end +end diff --git a/app/views/api/v2/fiber/graph_channels/index.jbuilder b/app/views/api/v2/fiber/graph_channels/index.jbuilder new file mode 100644 index 000000000..a53cbb927 --- /dev/null +++ b/app/views/api/v2/fiber/graph_channels/index.jbuilder @@ -0,0 +1,17 @@ +json.data do + json.fiber_graph_channels @channels do |channel| + json.(channel, :channel_outpoint, :node1, :node2, :chain_hash, :open_transaction_info, :closed_transaction_info) + json.funding_tx_block_number channel.funding_tx_block_number.to_s + json.funding_tx_index channel.funding_tx_index.to_s + json.last_updated_timestamp channel.last_updated_timestamp.to_s + json.created_timestamp channel.created_timestamp.to_s + json.node1_to_node2_fee_rate channel.node1_to_node2_fee_rate.to_s + json.node2_to_node1_fee_rate channel.node2_to_node1_fee_rate.to_s + json.capacity channel.capacity.to_s + json.udt_cfg_info channel.udt_info + end +end +json.meta do + json.total @channels.total_count + json.page_size @page_size.to_i +end diff --git a/app/views/api/v2/fiber/graph_nodes/index.jbuilder b/app/views/api/v2/fiber/graph_nodes/index.jbuilder new file mode 100644 index 000000000..a0140cad1 --- /dev/null +++ b/app/views/api/v2/fiber/graph_nodes/index.jbuilder @@ -0,0 +1,13 @@ +json.data do + json.fiber_graph_nodes @nodes do |node| + json.(node, :alias, :node_id, :addresses, :peer_id, :timestamp, :chain_hash, :connected_node_ids, :open_channels_count) + json.timestamp node.timestamp.to_s + json.auto_accept_min_ckb_funding_amount node.auto_accept_min_ckb_funding_amount.to_s + json.total_capacity node.total_capacity.to_s + json.udt_cfg_infos node.udt_cfg_infos + end +end +json.meta do + json.total @nodes.total_count + json.page_size @page_size.to_i +end diff --git a/app/views/api/v2/fiber/graph_nodes/show.jbuilder b/app/views/api/v2/fiber/graph_nodes/show.jbuilder new file mode 100644 index 000000000..d0dadbc14 --- /dev/null +++ b/app/views/api/v2/fiber/graph_nodes/show.jbuilder @@ -0,0 +1,18 @@ +json.data do + json.(@node, :alias, :node_id, :addresses, :peer_id, :timestamp, :chain_hash, :connected_node_ids) + json.timestamp @node.timestamp.to_s + json.auto_accept_min_ckb_funding_amount @node.auto_accept_min_ckb_funding_amount.to_s + json.total_capacity @node.total_capacity.to_s + json.udt_cfg_infos @node.udt_cfg_infos + + json.fiber_graph_channels @graph_channels do |channel| + json.(channel, :channel_outpoint, :node1, :node2, :chain_hash, :open_transaction_info, :closed_transaction_info) + json.funding_tx_block_number channel.funding_tx_block_number.to_s + json.funding_tx_index channel.funding_tx_index.to_s + json.last_updated_timestamp channel.last_updated_timestamp.to_s + json.created_timestamp channel.created_timestamp.to_s + json.node1_to_node2_fee_rate channel.node1_to_node2_fee_rate.to_s + json.node2_to_node1_fee_rate channel.node2_to_node1_fee_rate.to_s + json.capacity channel.capacity.to_s + end +end diff --git a/app/views/api/v2/fiber/peers/index.jbuilder b/app/views/api/v2/fiber/peers/index.jbuilder new file mode 100644 index 000000000..2566792ca --- /dev/null +++ b/app/views/api/v2/fiber/peers/index.jbuilder @@ -0,0 +1,10 @@ +json.data do + json.fiber_peers @peers do |peer| + json.(peer, :name, :peer_id, :rpc_listening_addr, :first_channel_opened_at,:last_channel_updated_at, :channels_count) + json.total_local_balance peer.total_local_balance.to_s + end +end +json.meta do + json.total @peers.total_count + json.page_size @page_size.to_i +end diff --git a/app/views/api/v2/fiber/peers/show.jbuilder b/app/views/api/v2/fiber/peers/show.jbuilder new file mode 100644 index 000000000..2ea20791f --- /dev/null +++ b/app/views/api/v2/fiber/peers/show.jbuilder @@ -0,0 +1,9 @@ +json.data do + json.(@peer, :peer_id, :rpc_listening_addr, :first_channel_opened_at, :last_channel_updated_at) + json.fiber_channels @peer.fiber_channels do |peer_channel| + json.peer_id peer_channel.peer_id + json.channel_id peer_channel.channel_id + json.state_name peer_channel.state_name + json.state_flags peer_channel.state_flags + end +end diff --git a/app/workers/fiber_detect_worker.rb b/app/workers/fiber_detect_worker.rb new file mode 100644 index 000000000..6fef6759b --- /dev/null +++ b/app/workers/fiber_detect_worker.rb @@ -0,0 +1,49 @@ +class FiberDetectWorker + include Sidekiq::Worker + sidekiq_options queue: "fiber" + + def perform(peer_id = nil) + fiber_peers = peer_id.present? ? FiberPeer.where(peer_id:) : FiberPeer.all + fiber_peers.each { sync_with_fiber_channels(_1) } + end + + private + + def sync_with_fiber_channels(fiber_peer) + channels_attributes = build_channels_attributes(fiber_peer) + FiberChannel.upsert_all(channels_attributes, unique_by: %i[peer_id channel_id]) + end + + def build_channels_attributes(fiber_peer) + data = rpc.list_channels(fiber_peer.rpc_listening_addr, { peer_id: nil }) + data["result"]["channels"].map do |channel| + { + fiber_peer_id: fiber_peer.id, + peer_id: channel["peer_id"], + channel_id: channel["channel_id"], + state_name: channel["state"]["state_name"], + state_flags: parse_state_flags(channel["state"]["state_flags"]), + local_balance: channel["local_balance"].to_i(16), + offered_tlc_balance: channel["offered_tlc_balance"].to_i(16), + remote_balance: channel["remote_balance"].to_i(16), + received_tlc_balance: channel["received_tlc_balance"].to_i(16), + created_at: Time.at(channel["created_at"].to_i(16) / 10**6), + } + end + end + + def parse_state_flags(flags) + case flags + when Array + flags + when String + flags.split("|") + else + [] + end + end + + def rpc + @rpc ||= FiberCoordinator.instance + end +end diff --git a/app/workers/fiber_graph_detect_worker.rb b/app/workers/fiber_graph_detect_worker.rb new file mode 100644 index 000000000..b729b88fe --- /dev/null +++ b/app/workers/fiber_graph_detect_worker.rb @@ -0,0 +1,122 @@ +class FiberGraphDetectWorker + include Sidekiq::Worker + sidekiq_options queue: "fiber" + + def perform + # sync graph nodes and channels + ["nodes", "channels"].each { fetch_graph_infos(_1) } + + # check channel is closed + FiberGraphChannel.open_channels.each do |channel| + funding_cell = channel.funding_cell + if funding_cell.consumed_by + channel.update(closed_transaction_id: funding_cell.consumed_by_id) + end + end + end + + private + + def fetch_graph_infos(data_type) + return if ENV["FIBER_NODE_URL"].blank? + + cursor = nil + + loop do + break if cursor == "0x" + + next_cursor = send("fetch_#{data_type}", cursor) + break if next_cursor.nil? || next_cursor == cursor + + cursor = next_cursor + end + end + + def fetch_nodes(last_cursor) + data = rpc.graph_nodes(ENV["FIBER_NODE_URL"], { limit: "0x64", after: last_cursor }) + ApplicationRecord.transaction { data.dig("result", "nodes").each { upsert_node_with_cfg_info(_1) } } + data.dig("result", "last_cursor") + rescue StandardError => e + Rails.logger.error("Error fetching nodes: #{e.message}") + nil + end + + def fetch_channels(last_cursor) + data = rpc.graph_channels(ENV["FIBER_NODE_URL"], { limit: "0x64", after: last_cursor }) + channel_attributes = data.dig("result", "channels").map { build_channel_attributes(_1) }.compact + FiberGraphChannel.upsert_all(channel_attributes, unique_by: %i[channel_outpoint]) if channel_attributes.any? + data.dig("result", "last_cursor") + rescue StandardError => e + Rails.logger.error("Error fetching channels: #{e.message}") + nil + end + + def upsert_node_with_cfg_info(node) + node_attributes = { + alias: node["alias"], + node_id: node["node_id"], + addresses: node["addresses"], + timestamp: node["timestamp"].to_i(16), + chain_hash: node["chain_hash"], + peer_id: extract_peer_id(node["addresses"]), + auto_accept_min_ckb_funding_amount: node["auto_accept_min_ckb_funding_amount"], + } + + fiber_graph_node = FiberGraphNode.upsert(node_attributes, unique_by: %i[node_id], returning: %i[id]) + + return unless fiber_graph_node && node["udt_cfg_infos"].present? + + cfg_info_attributes = node["udt_cfg_infos"].map do |info| + udt = Udt.find_by(info["script"].symbolize_keys) + next unless udt + + { + fiber_graph_node_id: fiber_graph_node[0]["id"], + udt_id: udt.id, + auto_accept_amount: info["auto_accept_amount"].to_i(16), + } + end.compact + + FiberUdtCfgInfo.upsert_all(cfg_info_attributes, unique_by: %i[fiber_graph_node_id udt_id]) if cfg_info_attributes.any? + end + + def build_channel_attributes(channel) + if (udt_type_script = channel["udt_type_script"]).present? + udt = Udt.find_by(udt_type_script.symbolize_keys) + end + + channel_outpoint = channel["channel_outpoint"] + open_transaction = CkbTransaction.find_by(tx_hash: channel_outpoint[0..65]) + + { + channel_outpoint:, + funding_tx_block_number: channel["funding_tx_block_number"].to_i(16), + funding_tx_index: channel["funding_tx_index"].to_i(16), + node1: channel["node1"], + node2: channel["node2"], + last_updated_timestamp: channel["last_updated_timestamp"].to_i(16), + created_timestamp: channel["created_timestamp"], + node1_to_node2_fee_rate: channel["node1_to_node2_fee_rate"].to_i(16), + node2_to_node1_fee_rate: channel["node2_to_node1_fee_rate"].to_i(16), + capacity: channel["capacity"].to_i(16), + chain_hash: channel["chain_hash"], + open_transaction_id: open_transaction&.id, + udt_id: udt&.id, + } + end + + def extract_peer_id(addresses) + return nil if addresses.blank? + + parts = addresses[0].split("/") + p2p_index = parts.index("p2p") || parts.index("ipfs") + + if p2p_index && parts.length > p2p_index + 1 + parts[p2p_index + 1] + end + end + + def rpc + @rpc ||= FiberCoordinator.instance + end +end diff --git a/config/routes/v2.rb b/config/routes/v2.rb index b431ae327..6a74404f9 100644 --- a/config/routes/v2.rb +++ b/config/routes/v2.rb @@ -100,5 +100,11 @@ get :udt_accounts, on: :member end resources :rgb_live_cells, only: :index + namespace :fiber do + resources :peers, param: :peer_id, only: %i[index show create] + resources :channels, param: :channel_id, only: :show + resources :graph_nodes, param: :node_id, only: %i[index show] + resources :graph_channels, only: :index + end end end diff --git a/config/settings.mainnet.yml b/config/settings.mainnet.yml index d48ef34e4..bbc2f5c80 100644 --- a/config/settings.mainnet.yml +++ b/config/settings.mainnet.yml @@ -92,3 +92,6 @@ btc_time_code_hash: - "0x70d64497a075bd651e98ac030455ea200637ee325a12ad08aff03f1a117e5a62" single_use_lock_code_hash: "0x8290467a512e5b9a6b816469b0edabba1f4ac474e28ffdd604c2a7c76446bbaf" + +# fiber funding lock code hash +fiber_funding_code_hash: "" diff --git a/config/settings.testnet.yml b/config/settings.testnet.yml index 3a6c5d389..790e071cd 100644 --- a/config/settings.testnet.yml +++ b/config/settings.testnet.yml @@ -95,3 +95,6 @@ btc_time_code_hash: - "0x80a09eca26d77cea1f5a69471c59481be7404febf40ee90f886c36a948385b55" single_use_lock_code_hash: "0x8290467a512e5b9a6b816469b0edabba1f4ac474e28ffdd604c2a7c76446bbaf" + +# fiber funding lock code hash +fiber_funding_code_hash: "0x6c67887fe201ee0c7853f1682c0b77c0e6214044c156c7558269390a8afa6d7c" diff --git a/config/sidekiq.yml b/config/sidekiq.yml index eb0df0b76..7054f09af 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -5,6 +5,7 @@ - critical - default - bitcoin + - fiber - low production: diff --git a/db/migrate/20240918024407_create_fiber_peers.rb b/db/migrate/20240918024407_create_fiber_peers.rb new file mode 100644 index 000000000..bb5aa2f31 --- /dev/null +++ b/db/migrate/20240918024407_create_fiber_peers.rb @@ -0,0 +1,13 @@ +class CreateFiberPeers < ActiveRecord::Migration[7.0] + def change + create_table :fiber_peers do |t| + t.string :name + t.string :peer_id + t.string :rpc_listening_addr + t.datetime :first_channel_opened_at + t.datetime :last_channel_updated_at + + t.timestamps + end + end +end diff --git a/db/migrate/20240918024415_create_fiber_channels.rb b/db/migrate/20240918024415_create_fiber_channels.rb new file mode 100644 index 000000000..7b536f5cf --- /dev/null +++ b/db/migrate/20240918024415_create_fiber_channels.rb @@ -0,0 +1,19 @@ +class CreateFiberChannels < ActiveRecord::Migration[7.0] + def change + create_table :fiber_channels do |t| + t.string :peer_id + t.string :channel_id + t.string :state_name + t.string :state_flags, default: [], array: true + t.decimal :local_balance, precision: 64, scale: 2, default: 0.0 + t.decimal :sent_tlc_balance, precision: 64, scale: 2, default: 0.0 + t.decimal :remote_balance, precision: 64, scale: 2, default: 0.0 + t.decimal :received_tlc_balance, precision: 64, scale: 2, default: 0.0 + t.datetime :shutdown_at + + t.timestamps + end + + add_index :fiber_channels, %i[peer_id channel_id], unique: true + end +end diff --git a/db/migrate/20240918033146_create_fiber_transactions.rb b/db/migrate/20240918033146_create_fiber_transactions.rb new file mode 100644 index 000000000..22f36d455 --- /dev/null +++ b/db/migrate/20240918033146_create_fiber_transactions.rb @@ -0,0 +1,11 @@ +class CreateFiberTransactions < ActiveRecord::Migration[7.0] + def change + create_table :fiber_transactions do |t| + t.integer :fiber_peer_id + t.integer :fiber_channel_id + t.integer :ckb_transaction_id + + t.timestamps + end + end +end diff --git a/db/migrate/20240920094807_add_fiber_peer_id_to_fiber_channels.rb b/db/migrate/20240920094807_add_fiber_peer_id_to_fiber_channels.rb new file mode 100644 index 000000000..375d2683d --- /dev/null +++ b/db/migrate/20240920094807_add_fiber_peer_id_to_fiber_channels.rb @@ -0,0 +1,7 @@ +class AddFiberPeerIdToFiberChannels < ActiveRecord::Migration[7.0] + def change + rename_column :fiber_channels, :sent_tlc_balance, :offered_tlc_balance + add_column :fiber_channels, :fiber_peer_id, :integer + add_index :fiber_channels, :fiber_peer_id + end +end diff --git a/db/migrate/20240924065539_update_rpc_listening_addr_to_array.rb b/db/migrate/20240924065539_update_rpc_listening_addr_to_array.rb new file mode 100644 index 000000000..d70a90ca4 --- /dev/null +++ b/db/migrate/20240924065539_update_rpc_listening_addr_to_array.rb @@ -0,0 +1,5 @@ +class UpdateRpcListeningAddrToArray < ActiveRecord::Migration[7.0] + def change + change_column :fiber_peers, :rpc_listening_addr, :string, array: true, default: [], using: "(string_to_array(rpc_listening_addr, ','))" + end +end diff --git a/db/migrate/20241012014906_create_fiber_graph_infos.rb b/db/migrate/20241012014906_create_fiber_graph_infos.rb new file mode 100644 index 000000000..39637c7d0 --- /dev/null +++ b/db/migrate/20241012014906_create_fiber_graph_infos.rb @@ -0,0 +1,33 @@ +class CreateFiberGraphInfos < ActiveRecord::Migration[7.0] + def change + create_table :fiber_graph_nodes do |t| + t.string :alias + t.string :node_id + t.string :addresses, array: true, default: [], using: "(string_to_array(addresses, ','))" + t.bigint :timestamp + t.string :chain_hash + t.decimal :auto_accept_min_ckb_funding_amount, precision: 30 + + t.timestamps + end + + create_table :fiber_graph_channels do |t| + t.string :channel_outpoint + t.bigint :funding_tx_block_number + t.integer :funding_tx_index + t.string :node1 + t.string :node2 + t.bigint :last_updated_timestamp + t.bigint :created_timestamp + t.decimal :node1_to_node2_fee_rate, precision: 30, default: 0.0 + t.decimal :node2_to_node1_fee_rate, precision: 30, default: 0.0 + t.decimal :capacity, precision: 64, scale: 2, default: 0.0 + t.string :chain_hash + + t.timestamps + end + + add_index :fiber_graph_nodes, :node_id, unique: true + add_index :fiber_graph_channels, :channel_outpoint, unique: true + end +end diff --git a/db/migrate/20241023055256_create_fiber_udt_cfg_infos.rb b/db/migrate/20241023055256_create_fiber_udt_cfg_infos.rb new file mode 100644 index 000000000..54faa718a --- /dev/null +++ b/db/migrate/20241023055256_create_fiber_udt_cfg_infos.rb @@ -0,0 +1,13 @@ +class CreateFiberUdtCfgInfos < ActiveRecord::Migration[7.0] + def change + create_table :fiber_udt_cfg_infos do |t| + t.bigint :fiber_graph_node_id + t.bigint :udt_id + t.decimal :auto_accept_amount, precision: 64, scale: 2, default: 0.0 + + t.timestamps + end + + add_index :fiber_udt_cfg_infos, %i[fiber_graph_node_id udt_id], unique: true + end +end diff --git a/db/migrate/20241023063536_add_udt_id_to_fiber_graph_channels.rb b/db/migrate/20241023063536_add_udt_id_to_fiber_graph_channels.rb new file mode 100644 index 000000000..20c001b16 --- /dev/null +++ b/db/migrate/20241023063536_add_udt_id_to_fiber_graph_channels.rb @@ -0,0 +1,5 @@ +class AddUdtIdToFiberGraphChannels < ActiveRecord::Migration[7.0] + def change + add_column :fiber_graph_channels, :udt_id, :bigint + end +end diff --git a/db/migrate/20241030023309_add_transaction_id_to_fiber_graph_channels.rb b/db/migrate/20241030023309_add_transaction_id_to_fiber_graph_channels.rb new file mode 100644 index 000000000..212379ae3 --- /dev/null +++ b/db/migrate/20241030023309_add_transaction_id_to_fiber_graph_channels.rb @@ -0,0 +1,8 @@ +class AddTransactionIdToFiberGraphChannels < ActiveRecord::Migration[7.0] + def change + change_table :fiber_graph_channels, bulk: true do |t| + t.bigint :open_transaction_id + t.bigint :closed_transaction_id + end + end +end diff --git a/db/migrate/20241129032447_add_peer_id_to_fiber_graph_nodes.rb b/db/migrate/20241129032447_add_peer_id_to_fiber_graph_nodes.rb new file mode 100644 index 000000000..f25285b0e --- /dev/null +++ b/db/migrate/20241129032447_add_peer_id_to_fiber_graph_nodes.rb @@ -0,0 +1,5 @@ +class AddPeerIdToFiberGraphNodes < ActiveRecord::Migration[7.0] + def change + add_column :fiber_graph_nodes, :peer_id, :string + end +end diff --git a/db/structure.sql b/db/structure.sql index bbe7b508d..b1b2bedbb 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -23,20 +23,6 @@ CREATE EXTENSION IF NOT EXISTS btree_gin WITH SCHEMA public; COMMENT ON EXTENSION btree_gin IS 'support for indexing common datatypes in GIN'; --- --- Name: pg_buffercache; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS pg_buffercache WITH SCHEMA public; - - --- --- Name: EXTENSION pg_buffercache; Type: COMMENT; Schema: -; Owner: - --- - -COMMENT ON EXTENSION pg_buffercache IS 'examine the shared buffer cache'; - - -- -- Name: array_subtract(anyarray, anyarray); Type: FUNCTION; Schema: public; Owner: - -- @@ -188,7 +174,7 @@ begin insert into account_books (ckb_transaction_id, address_id) values (row.id, i) ON CONFLICT DO NOTHING; end loop; - END LOOP; + END LOOP; close c; end $$; @@ -210,21 +196,21 @@ DECLARE if new.contained_address_ids is null then new.contained_address_ids := array[]::int[]; end if; - if old is null + if old is null then to_add := new.contained_address_ids; to_remove := array[]::int[]; else - + to_add := array_subtract(new.contained_address_ids, old.contained_address_ids); - to_remove := array_subtract(old.contained_address_ids, new.contained_address_ids); + to_remove := array_subtract(old.contained_address_ids, new.contained_address_ids); end if; if to_add is not null then FOREACH i IN ARRAY to_add - LOOP + LOOP RAISE NOTICE 'ckb_tx_addr_id(%)', i; - insert into account_books (ckb_transaction_id, address_id) + insert into account_books (ckb_transaction_id, address_id) values (new.id, i); END LOOP; end if; @@ -429,9 +415,9 @@ CREATE TABLE public.addresses ( dao_deposit numeric(30,0) DEFAULT 0.0, interest numeric(30,0) DEFAULT 0.0, block_timestamp bigint, - visible boolean DEFAULT true, live_cells_count bigint DEFAULT 0.0, mined_blocks_count integer DEFAULT 0, + visible boolean DEFAULT true, average_deposit_time bigint, unclaimed_compensation numeric(30,0), is_depositor boolean DEFAULT false, @@ -484,6 +470,7 @@ CREATE TABLE public.blocks ( "timestamp" bigint, transactions_root bytea, proposals_hash bytea, + uncles_count integer, extra_hash bytea, uncle_block_hashes bytea, version integer, @@ -510,7 +497,6 @@ CREATE TABLE public.blocks ( nonce numeric(50,0) DEFAULT 0.0, start_number numeric(30,0) DEFAULT 0.0, length numeric(30,0) DEFAULT 0.0, - uncles_count integer, compact_target numeric(20,0), live_cell_changes integer, block_time bigint, @@ -520,8 +506,8 @@ CREATE TABLE public.blocks ( miner_message character varying, extension jsonb, median_timestamp bigint DEFAULT 0.0, - cycles bigint, - ckb_node_version character varying + ckb_node_version character varying, + cycles bigint ); @@ -672,6 +658,39 @@ CREATE SEQUENCE public.bitcoin_statistics_id_seq ALTER SEQUENCE public.bitcoin_statistics_id_seq OWNED BY public.bitcoin_statistics.id; +-- +-- Name: bitcoin_time_locks; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.bitcoin_time_locks ( + id bigint NOT NULL, + bitcoin_transaction_id bigint, + ckb_transaction_id bigint, + cell_output_id bigint, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: bitcoin_time_locks_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.bitcoin_time_locks_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: bitcoin_time_locks_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.bitcoin_time_locks_id_seq OWNED BY public.bitcoin_time_locks.id; + + -- -- Name: bitcoin_transactions; Type: TABLE; Schema: public; Owner: - -- @@ -1516,9 +1535,9 @@ ALTER SEQUENCE public.contracts_id_seq OWNED BY public.contracts.id; CREATE TABLE public.daily_statistics ( id bigint NOT NULL, - transactions_count character varying DEFAULT '0'::character varying, - addresses_count character varying DEFAULT '0'::character varying, - total_dao_deposit character varying DEFAULT '0.0'::character varying, + transactions_count character varying DEFAULT 0, + addresses_count character varying DEFAULT 0, + total_dao_deposit character varying DEFAULT 0.0, block_timestamp numeric(30,0), created_at_unixtimestamp integer, created_at timestamp(6) without time zone NOT NULL, @@ -1537,8 +1556,8 @@ CREATE TABLE public.daily_statistics ( avg_difficulty character varying DEFAULT '0'::character varying, uncle_rate character varying DEFAULT '0'::character varying, total_depositors_count character varying DEFAULT '0'::character varying, - address_balance_distribution jsonb, total_tx_fee numeric(30,0), + address_balance_distribution jsonb, occupied_capacity numeric(30,0), daily_dao_deposit numeric(30,0), daily_dao_depositors_count integer, @@ -1728,6 +1747,230 @@ CREATE SEQUENCE public.epoch_statistics_id_seq ALTER SEQUENCE public.epoch_statistics_id_seq OWNED BY public.epoch_statistics.id; +-- +-- Name: fiber_channels; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_channels ( + id bigint NOT NULL, + peer_id character varying, + channel_id character varying, + state_name character varying, + state_flags character varying[] DEFAULT '{}'::character varying[], + local_balance numeric(64,2) DEFAULT 0.0, + offered_tlc_balance numeric(64,2) DEFAULT 0.0, + remote_balance numeric(64,2) DEFAULT 0.0, + received_tlc_balance numeric(64,2) DEFAULT 0.0, + shutdown_at timestamp(6) without time zone, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + fiber_peer_id integer +); + + +-- +-- Name: fiber_channels_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_channels_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_channels_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_channels_id_seq OWNED BY public.fiber_channels.id; + + +-- +-- Name: fiber_graph_channels; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_graph_channels ( + id bigint NOT NULL, + channel_outpoint character varying, + funding_tx_block_number bigint, + funding_tx_index integer, + node1 character varying, + node2 character varying, + last_updated_timestamp bigint, + created_timestamp bigint, + node1_to_node2_fee_rate numeric(30,0) DEFAULT 0.0, + node2_to_node1_fee_rate numeric(30,0) DEFAULT 0.0, + capacity numeric(64,2) DEFAULT 0.0, + chain_hash character varying, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + udt_id bigint, + open_transaction_id bigint, + closed_transaction_id bigint +); + + +-- +-- Name: fiber_graph_channels_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_graph_channels_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_graph_channels_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_graph_channels_id_seq OWNED BY public.fiber_graph_channels.id; + + +-- +-- Name: fiber_graph_nodes; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_graph_nodes ( + id bigint NOT NULL, + alias character varying, + node_id character varying, + addresses character varying[] DEFAULT '{}'::character varying[], + "timestamp" bigint, + chain_hash character varying, + auto_accept_min_ckb_funding_amount numeric(30,0), + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + peer_id character varying +); + + +-- +-- Name: fiber_graph_nodes_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_graph_nodes_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_graph_nodes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_graph_nodes_id_seq OWNED BY public.fiber_graph_nodes.id; + + +-- +-- Name: fiber_peers; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_peers ( + id bigint NOT NULL, + name character varying, + peer_id character varying, + rpc_listening_addr character varying[] DEFAULT '{}'::character varying[], + first_channel_opened_at timestamp(6) without time zone, + last_channel_updated_at timestamp(6) without time zone, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + node_id character varying, + chain_hash character varying +); + + +-- +-- Name: fiber_peers_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_peers_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_peers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_peers_id_seq OWNED BY public.fiber_peers.id; + + +-- +-- Name: fiber_transactions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_transactions ( + id bigint NOT NULL, + fiber_peer_id integer, + fiber_channel_id integer, + ckb_transaction_id integer, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: fiber_transactions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_transactions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_transactions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_transactions_id_seq OWNED BY public.fiber_transactions.id; + + +-- +-- Name: fiber_udt_cfg_infos; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.fiber_udt_cfg_infos ( + id bigint NOT NULL, + fiber_graph_node_id bigint, + udt_id bigint, + auto_accept_amount numeric(64,2) DEFAULT 0.0, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: fiber_udt_cfg_infos_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.fiber_udt_cfg_infos_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: fiber_udt_cfg_infos_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.fiber_udt_cfg_infos_id_seq OWNED BY public.fiber_udt_cfg_infos.id; + + -- -- Name: forked_blocks; Type: TABLE; Schema: public; Owner: - -- @@ -1740,6 +1983,7 @@ CREATE TABLE public.forked_blocks ( "timestamp" bigint, transactions_root bytea, proposals_hash bytea, + uncles_count integer, extra_hash bytea, uncle_block_hashes bytea, version integer, @@ -1766,7 +2010,6 @@ CREATE TABLE public.forked_blocks ( nonce numeric(50,0) DEFAULT 0.0, start_number numeric(30,0) DEFAULT 0.0, length numeric(30,0) DEFAULT 0.0, - uncles_count integer, compact_target numeric(20,0), live_cell_changes integer, block_time numeric(13,0), @@ -1776,8 +2019,8 @@ CREATE TABLE public.forked_blocks ( miner_message character varying, extension jsonb, median_timestamp numeric DEFAULT 0.0, - cycles bigint, - ckb_node_version character varying + ckb_node_version character varying, + cycles bigint ); @@ -2961,6 +3204,13 @@ ALTER TABLE ONLY public.bitcoin_annotations ALTER COLUMN id SET DEFAULT nextval( ALTER TABLE ONLY public.bitcoin_statistics ALTER COLUMN id SET DEFAULT nextval('public.bitcoin_statistics_id_seq'::regclass); +-- +-- Name: bitcoin_time_locks id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.bitcoin_time_locks ALTER COLUMN id SET DEFAULT nextval('public.bitcoin_time_locks_id_seq'::regclass); + + -- -- Name: bitcoin_transactions id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3108,6 +3358,48 @@ ALTER TABLE ONLY public.deployed_cells ALTER COLUMN id SET DEFAULT nextval('publ ALTER TABLE ONLY public.epoch_statistics ALTER COLUMN id SET DEFAULT nextval('public.epoch_statistics_id_seq'::regclass); +-- +-- Name: fiber_channels id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_channels ALTER COLUMN id SET DEFAULT nextval('public.fiber_channels_id_seq'::regclass); + + +-- +-- Name: fiber_graph_channels id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_graph_channels ALTER COLUMN id SET DEFAULT nextval('public.fiber_graph_channels_id_seq'::regclass); + + +-- +-- Name: fiber_graph_nodes id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_graph_nodes ALTER COLUMN id SET DEFAULT nextval('public.fiber_graph_nodes_id_seq'::regclass); + + +-- +-- Name: fiber_peers id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_peers ALTER COLUMN id SET DEFAULT nextval('public.fiber_peers_id_seq'::regclass); + + +-- +-- Name: fiber_transactions id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_transactions ALTER COLUMN id SET DEFAULT nextval('public.fiber_transactions_id_seq'::regclass); + + +-- +-- Name: fiber_udt_cfg_infos id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_udt_cfg_infos ALTER COLUMN id SET DEFAULT nextval('public.fiber_udt_cfg_infos_id_seq'::regclass); + + -- -- Name: forked_blocks id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3375,6 +3667,14 @@ ALTER TABLE ONLY public.bitcoin_statistics ADD CONSTRAINT bitcoin_statistics_pkey PRIMARY KEY (id); +-- +-- Name: bitcoin_time_locks bitcoin_time_locks_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.bitcoin_time_locks + ADD CONSTRAINT bitcoin_time_locks_pkey PRIMARY KEY (id); + + -- -- Name: bitcoin_transactions bitcoin_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -3647,6 +3947,54 @@ ALTER TABLE ONLY public.epoch_statistics ADD CONSTRAINT epoch_statistics_pkey PRIMARY KEY (id); +-- +-- Name: fiber_channels fiber_channels_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_channels + ADD CONSTRAINT fiber_channels_pkey PRIMARY KEY (id); + + +-- +-- Name: fiber_graph_channels fiber_graph_channels_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_graph_channels + ADD CONSTRAINT fiber_graph_channels_pkey PRIMARY KEY (id); + + +-- +-- Name: fiber_graph_nodes fiber_graph_nodes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_graph_nodes + ADD CONSTRAINT fiber_graph_nodes_pkey PRIMARY KEY (id); + + +-- +-- Name: fiber_peers fiber_peers_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_peers + ADD CONSTRAINT fiber_peers_pkey PRIMARY KEY (id); + + +-- +-- Name: fiber_transactions fiber_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_transactions + ADD CONSTRAINT fiber_transactions_pkey PRIMARY KEY (id); + + +-- +-- Name: fiber_udt_cfg_infos fiber_udt_cfg_infos_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.fiber_udt_cfg_infos + ADD CONSTRAINT fiber_udt_cfg_infos_pkey PRIMARY KEY (id); + + -- -- Name: forked_blocks forked_blocks_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4513,6 +4861,13 @@ CREATE UNIQUE INDEX index_bitcoin_annotations_on_ckb_transaction_id ON public.bi CREATE UNIQUE INDEX index_bitcoin_statistics_on_timestamp ON public.bitcoin_statistics USING btree ("timestamp"); +-- +-- Name: index_bitcoin_time_locks_on_cell; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_bitcoin_time_locks_on_cell ON public.bitcoin_time_locks USING btree (bitcoin_transaction_id, cell_output_id); + + -- -- Name: index_bitcoin_transactions_on_txid; Type: INDEX; Schema: public; Owner: - -- @@ -4800,6 +5155,48 @@ CREATE UNIQUE INDEX index_deployed_cells_on_contract_id_and_cell_output_id ON pu CREATE UNIQUE INDEX index_epoch_statistics_on_epoch_number ON public.epoch_statistics USING btree (epoch_number); +-- +-- Name: index_fiber_channels_on_fiber_peer_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_fiber_channels_on_fiber_peer_id ON public.fiber_channels USING btree (fiber_peer_id); + + +-- +-- Name: index_fiber_channels_on_peer_id_and_channel_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_fiber_channels_on_peer_id_and_channel_id ON public.fiber_channels USING btree (peer_id, channel_id); + + +-- +-- Name: index_fiber_graph_channels_on_channel_outpoint; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_fiber_graph_channels_on_channel_outpoint ON public.fiber_graph_channels USING btree (channel_outpoint); + + +-- +-- Name: index_fiber_graph_nodes_on_node_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_fiber_graph_nodes_on_node_id ON public.fiber_graph_nodes USING btree (node_id); + + +-- +-- Name: index_fiber_peers_on_peer_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_fiber_peers_on_peer_id ON public.fiber_peers USING btree (peer_id); + + +-- +-- Name: index_fiber_udt_cfg_infos_on_fiber_graph_node_id_and_udt_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_fiber_udt_cfg_infos_on_fiber_graph_node_id_and_udt_id ON public.fiber_udt_cfg_infos USING btree (fiber_graph_node_id, udt_id); + + -- -- Name: index_forked_events_on_status; Type: INDEX; Schema: public; Owner: - -- @@ -4905,6 +5302,13 @@ CREATE INDEX index_on_cell_dependencies_contract_cell_block_tx ON public.cell_de CREATE UNIQUE INDEX index_portfolios_on_user_id_and_address_id ON public.portfolios USING btree (user_id, address_id); +-- +-- Name: index_referring_cells_on_cell_output_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_referring_cells_on_cell_output_id ON public.referring_cells USING btree (cell_output_id); + + -- -- Name: index_referring_cells_on_contract_id_and_cell_output_id; Type: INDEX; Schema: public; Owner: - -- @@ -6018,6 +6422,15 @@ INSERT INTO "schema_migrations" (version) VALUES ('20240823071420'), ('20240902025657'), ('20240904043807'), +('20240918024407'), +('20240918024415'), +('20240918033146'), +('20240920094807'), +('20240924065539'), +('20241012014906'), +('20241023055256'), +('20241023063536'), +('20241030023309'), ('20241105070340'), ('20241105070619'), ('20241106062022'), @@ -6026,6 +6439,5 @@ INSERT INTO "schema_migrations" (version) VALUES ('20241121073245'), ('20241125100650'), ('20241129000339'), +('20241129032447'), ('20241202072604'); - - diff --git a/lib/scheduler.rb b/lib/scheduler.rb index 364ab7997..9afe16d6f 100644 --- a/lib/scheduler.rb +++ b/lib/scheduler.rb @@ -132,4 +132,8 @@ def call_worker(clz) call_worker AnalyzeContractFromCellDependencyWorker end +s.every "5m", overlap: false do + call_worker FiberGraphDetectWorker +end + s.join diff --git a/test/factories/fiber_channels.rb b/test/factories/fiber_channels.rb new file mode 100644 index 000000000..7a55b0264 --- /dev/null +++ b/test/factories/fiber_channels.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :fiber_channel do + + end +end diff --git a/test/factories/fiber_graph_channels.rb b/test/factories/fiber_graph_channels.rb new file mode 100644 index 000000000..f63ba3d55 --- /dev/null +++ b/test/factories/fiber_graph_channels.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :fiber_graph_channel do + + end +end diff --git a/test/factories/fiber_graph_nodes.rb b/test/factories/fiber_graph_nodes.rb new file mode 100644 index 000000000..a387eeb93 --- /dev/null +++ b/test/factories/fiber_graph_nodes.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :fiber_graph_node do + + end +end diff --git a/test/factories/fiber_peers.rb b/test/factories/fiber_peers.rb new file mode 100644 index 000000000..96b8b3aa3 --- /dev/null +++ b/test/factories/fiber_peers.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :fiber_peer do + + end +end diff --git a/test/factories/fiber_udt_cfg_infos.rb b/test/factories/fiber_udt_cfg_infos.rb new file mode 100644 index 000000000..f9cbd8b2a --- /dev/null +++ b/test/factories/fiber_udt_cfg_infos.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :fiber_udt_cfg_info do + + end +end diff --git a/test/models/fiber_channel_test.rb b/test/models/fiber_channel_test.rb new file mode 100644 index 000000000..25e751ac1 --- /dev/null +++ b/test/models/fiber_channel_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class FiberChannelTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/fiber_graph_channel_test.rb b/test/models/fiber_graph_channel_test.rb new file mode 100644 index 000000000..d9674a776 --- /dev/null +++ b/test/models/fiber_graph_channel_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class FiberGraphChannelTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/fiber_graph_node_test.rb b/test/models/fiber_graph_node_test.rb new file mode 100644 index 000000000..ef430b005 --- /dev/null +++ b/test/models/fiber_graph_node_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class FiberGraphNodeTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/fiber_peer_test.rb b/test/models/fiber_peer_test.rb new file mode 100644 index 000000000..f179352d2 --- /dev/null +++ b/test/models/fiber_peer_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class FiberPeerTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/fiber_udt_cfg_info_test.rb b/test/models/fiber_udt_cfg_info_test.rb new file mode 100644 index 000000000..80fdf45d9 --- /dev/null +++ b/test/models/fiber_udt_cfg_info_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class FiberUdtCfgInfoTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 33927e061855f9fce92774781cece60568b269d8 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Thu, 5 Dec 2024 20:07:35 +0900 Subject: [PATCH 05/11] fix: keep unique analyze job (#2310) Signed-off-by: Miles Zhang --- app/workers/analyze_contract_from_cell_dependency_worker.rb | 3 ++- config/sidekiq.yml | 3 +++ lib/scheduler.rb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/workers/analyze_contract_from_cell_dependency_worker.rb b/app/workers/analyze_contract_from_cell_dependency_worker.rb index 9c2edd825..fb01a2782 100644 --- a/app/workers/analyze_contract_from_cell_dependency_worker.rb +++ b/app/workers/analyze_contract_from_cell_dependency_worker.rb @@ -1,12 +1,13 @@ class AnalyzeContractFromCellDependencyWorker include Sidekiq::Worker + sidekiq_options queue: "contract", retry: 0 def perform cell_deps_out_points_attrs = Set.new contract_attrs = Set.new cell_deps_attrs = Set.new - CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(1000).each do |cell_dep| + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).limit(1000).each do |cell_dep| cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 7054f09af..f151bd024 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -7,6 +7,9 @@ - bitcoin - fiber - low + - contract +:limits: + contract: 1 production: :concurrency: 20 diff --git a/lib/scheduler.rb b/lib/scheduler.rb index 9afe16d6f..e5f6efb5f 100644 --- a/lib/scheduler.rb +++ b/lib/scheduler.rb @@ -128,7 +128,7 @@ def call_worker(clz) call_worker GenerateUdtHolderAllocationWorker end -s.every "5s", overlap: false do +s.every "10s", overlap: false do call_worker AnalyzeContractFromCellDependencyWorker end From 691a89f83f8f3710770c3d03d169d71f51e04b94 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Thu, 5 Dec 2024 20:25:40 +0900 Subject: [PATCH 06/11] feat: speed up AnalyzeContractFromCellDependencyWorker (#2312) Signed-off-by: Miles Zhang --- app/workers/analyze_contract_from_cell_dependency_worker.rb | 2 +- lib/scheduler.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workers/analyze_contract_from_cell_dependency_worker.rb b/app/workers/analyze_contract_from_cell_dependency_worker.rb index fb01a2782..925102657 100644 --- a/app/workers/analyze_contract_from_cell_dependency_worker.rb +++ b/app/workers/analyze_contract_from_cell_dependency_worker.rb @@ -7,7 +7,7 @@ def perform contract_attrs = Set.new cell_deps_attrs = Set.new - CellDependency.where(contract_analyzed: false).where.not(block_number: nil).limit(1000).each do |cell_dep| + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(100).each do |cell_dep| cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? diff --git a/lib/scheduler.rb b/lib/scheduler.rb index e5f6efb5f..5da494ff1 100644 --- a/lib/scheduler.rb +++ b/lib/scheduler.rb @@ -128,7 +128,7 @@ def call_worker(clz) call_worker GenerateUdtHolderAllocationWorker end -s.every "10s", overlap: false do +s.every "2s", overlap: false do call_worker AnalyzeContractFromCellDependencyWorker end From abe5b8d4ff12dc584498090495886fb61241176b Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Thu, 5 Dec 2024 21:15:06 +0900 Subject: [PATCH 07/11] feat: use sidekiq-unique-jobs (#2314) Signed-off-by: Miles Zhang --- Gemfile | 1 + Gemfile.lock | 7 +++++- ...ze_contract_from_cell_dependency_worker.rb | 6 +++-- config/initializers/sidekiq.rb | 25 +++++++++++++------ config/routes.rb | 1 + config/sidekiq.yml | 3 --- lib/scheduler.rb | 2 +- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Gemfile b/Gemfile index 434a09bed..5469f6826 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,7 @@ gem "redis" # , "~> 4.2.0" # Background Jobs gem "rufus-scheduler" gem "sidekiq" +gem "sidekiq-unique-jobs" # bulk insertion of data into database using ActiveRecord gem "activerecord-import" diff --git a/Gemfile.lock b/Gemfile.lock index c7c4b930e..d1d6270aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -439,11 +439,15 @@ GEM shoulda-context (2.0.0) shoulda-matchers (5.2.0) activesupport (>= 5.2.0) - sidekiq (7.1.6) + sidekiq (7.2.0) concurrent-ruby (< 2) connection_pool (>= 2.3.0) rack (>= 2.2.4) redis-client (>= 0.14.0) + sidekiq-unique-jobs (8.0.10) + concurrent-ruby (~> 1.0, >= 1.0.5) + sidekiq (>= 7.0.0, < 8.0.0) + thor (>= 1.0, < 3.0) simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) @@ -544,6 +548,7 @@ DEPENDENCIES shoulda-context shoulda-matchers sidekiq + sidekiq-unique-jobs simplecov simplecov-cobertura spring diff --git a/app/workers/analyze_contract_from_cell_dependency_worker.rb b/app/workers/analyze_contract_from_cell_dependency_worker.rb index 925102657..a49a95d95 100644 --- a/app/workers/analyze_contract_from_cell_dependency_worker.rb +++ b/app/workers/analyze_contract_from_cell_dependency_worker.rb @@ -1,13 +1,15 @@ class AnalyzeContractFromCellDependencyWorker include Sidekiq::Worker - sidekiq_options queue: "contract", retry: 0 + + sidekiq_options queue: "critical", retry: 0 + sidekiq_options lock: :until_executed def perform cell_deps_out_points_attrs = Set.new contract_attrs = Set.new cell_deps_attrs = Set.new - CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(100).each do |cell_dep| + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(1000).each do |cell_dep| cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index b150e334c..6ec26ddd0 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,4 +1,5 @@ require "sidekiq/web" +require "sidekiq-unique-jobs" redis_config = Rails.application.config_for(:redis) redis_url = redis_config["url"] @@ -7,18 +8,26 @@ Sidekiq.strict_args!(false) Sidekiq.configure_server do |config| - config.redis = { url: redis_url, driver: :ruby, password: redis_password } - # config.redis = { url: redis_url, driver: :hiredis, password: redis_password } + # config.redis = { url: redis_url, driver: :ruby, password: redis_password } + config.redis = { url: redis_url, driver: :hiredis, password: redis_password } - if defined?(ActiveRecord::Base) - config = Rails.application.config.database_configuration[Rails.env] - config["reaping_frequency"] = ENV["DB_REAP_FREQ"] || 10 - ActiveRecord::Base.establish_connection(config) + config.client_middleware do |chain| + chain.add SidekiqUniqueJobs::Middleware::Client end + + config.server_middleware do |chain| + chain.add SidekiqUniqueJobs::Middleware::Server + end + + SidekiqUniqueJobs::Server.configure(config) end Sidekiq.configure_client do |config| - # config.redis = { url: redis_url, driver: :hiredis, password: redis_password } - config.redis = { url: redis_url, driver: :ruby, password: redis_password } + config.redis = { url: redis_url, driver: :hiredis, password: redis_password } + # config.redis = { url: redis_url, driver: :ruby, password: redis_password } + + config.client_middleware do |chain| + chain.add SidekiqUniqueJobs::Middleware::Client + end end # Auth sidekiq user in production env. diff --git a/config/routes.rb b/config/routes.rb index 152d7fa07..f8d2cf4a7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ require "sidekiq/web" +require "sidekiq_unique_jobs/web" Sidekiq::Web.use ActionDispatch::Cookies Sidekiq::Web.use ActionDispatch::Session::CookieStore diff --git a/config/sidekiq.yml b/config/sidekiq.yml index f151bd024..7054f09af 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -7,9 +7,6 @@ - bitcoin - fiber - low - - contract -:limits: - contract: 1 production: :concurrency: 20 diff --git a/lib/scheduler.rb b/lib/scheduler.rb index 5da494ff1..9afe16d6f 100644 --- a/lib/scheduler.rb +++ b/lib/scheduler.rb @@ -128,7 +128,7 @@ def call_worker(clz) call_worker GenerateUdtHolderAllocationWorker end -s.every "2s", overlap: false do +s.every "5s", overlap: false do call_worker AnalyzeContractFromCellDependencyWorker end From 6180b8c4499ad929e8bf480b5f68ac52523f3d0d Mon Sep 17 00:00:00 2001 From: Rabbit Date: Fri, 6 Dec 2024 10:04:01 +0800 Subject: [PATCH 08/11] chore: adjust tests (#2317) --- app/controllers/api/v2/portfolio/addresses_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/v2/portfolio/addresses_controller.rb b/app/controllers/api/v2/portfolio/addresses_controller.rb index 37d5b20fd..3925d326b 100644 --- a/app/controllers/api/v2/portfolio/addresses_controller.rb +++ b/app/controllers/api/v2/portfolio/addresses_controller.rb @@ -10,7 +10,7 @@ def create head :no_content rescue StandardError => e - raise Api::V2::Exceptions::ParamsInvalidError + raise Api::V2::Exceptions::SyncPortfolioAddressesError end end end From 6d7ea52a575b3a942b76d9867c3d6bd2a5cbe04e Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Fri, 6 Dec 2024 12:45:51 +0900 Subject: [PATCH 09/11] feat: remove deprecated code (#2308) Signed-off-by: Miles Zhang --- app/jobs/commit_block_job.rb | 30 -- app/jobs/import_block_job.rb | 17 - app/jobs/import_transaction_job.rb | 335 ------------------ app/jobs/revert_block_job.rb | 6 - app/models/cell_output.rb | 2 - .../ckb_sync/new_node_data_processor.rb | 55 +-- app/models/ckb_transaction.rb | 5 +- app/models/deployed_cell.rb | 195 ---------- app/models/distribution_data.rb | 25 +- app/models/lock_script.rb | 3 - app/models/referring_cell.rb | 61 ---- app/models/script.rb | 58 --- app/models/script_transaction.rb | 73 ---- app/models/transaction_propagation_delay.rb | 18 - app/models/type_script.rb | 3 - .../scripts_ckb_transactions_serializer.rb | 29 -- .../v2/scripts/deployed_cells.json.jbuilder | 29 -- .../v2/scripts/referring_cells.json.jbuilder | 29 -- .../generate_cell_dependencies_worker.rb | 20 -- app/workers/pool_transaction_check_worker.rb | 4 - ...9_drop_scripts_and_scripts_transactions.rb | 9 + db/structure.sql | 305 +--------------- .../migration/generate_referring_cells.rake | 54 --- test/jobs/import_transaction_job_test.rb | 138 -------- test/models/address_test.rb | 1 - test/models/block_test.rb | 1 - test/models/cell_output_test.rb | 5 +- test/models/ckb_sync/dao_events_test.rb | 1 - .../ckb_sync/node_data_processor_test.rb | 1 - test/models/ckb_transaction_test.rb | 2 - test/models/deployed_cell_test.rb | 172 --------- test/models/lock_script_test.rb | 1 - test/models/referring_cell_test.rb | 30 -- test/models/script_test.rb | 33 -- test/models/script_transaction_test.rb | 61 ---- test/models/type_script_test.rb | 1 - test/models/uncle_block_test.rb | 1 - test/test_helper.rb | 1 - test/utils/ckb_utils_test.rb | 1 - 39 files changed, 22 insertions(+), 1793 deletions(-) delete mode 100644 app/jobs/commit_block_job.rb delete mode 100644 app/jobs/import_block_job.rb delete mode 100644 app/jobs/import_transaction_job.rb delete mode 100644 app/models/deployed_cell.rb delete mode 100644 app/models/referring_cell.rb delete mode 100644 app/models/script.rb delete mode 100644 app/models/script_transaction.rb delete mode 100644 app/models/transaction_propagation_delay.rb delete mode 100644 app/serializers/scripts_ckb_transactions_serializer.rb delete mode 100644 app/views/api/v2/scripts/deployed_cells.json.jbuilder delete mode 100644 app/views/api/v2/scripts/referring_cells.json.jbuilder delete mode 100644 app/workers/generate_cell_dependencies_worker.rb create mode 100644 db/migrate/20241205023729_drop_scripts_and_scripts_transactions.rb delete mode 100644 lib/tasks/migration/generate_referring_cells.rake delete mode 100644 test/jobs/import_transaction_job_test.rb delete mode 100644 test/models/deployed_cell_test.rb delete mode 100644 test/models/referring_cell_test.rb delete mode 100644 test/models/script_test.rb delete mode 100644 test/models/script_transaction_test.rb diff --git a/app/jobs/commit_block_job.rb b/app/jobs/commit_block_job.rb deleted file mode 100644 index a678f27ad..000000000 --- a/app/jobs/commit_block_job.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Make specific block committed -# this will make the block's transactions committed -# make cell outputs generated to live -# set related statistic info, address info to latest state -class CommitBlockJob < ApplicationJob - def perform(block) - case block - when Integer - block = Block.find_by id: block - when String - block = Block.find_by block_hash: block - when Block - else - raise ArgumentError - end - - # binding.pry - block.contained_transactions.each do |tx| - end - - # reject all the other cell output that is consumed by - # transactions in current block - - # collect all the previous cell outputs - # select related cell inputs which are not in current block - # mark the transaction contains these cell input to be rejected - - # update some statistics and state - end -end diff --git a/app/jobs/import_block_job.rb b/app/jobs/import_block_job.rb deleted file mode 100644 index 58bd09cda..000000000 --- a/app/jobs/import_block_job.rb +++ /dev/null @@ -1,17 +0,0 @@ -# No used -class ImportBlockJob < ApplicationJob - def perform(block_hash) - if block_hash.is_a?(Integer) - block = Block.fetch_raw_hash_by_number(block_hash) - block_number = block_hash - block_hash = block["header"]["hash"] - else - block = Block.fetch_raw_hash(block_hash) - block_number = block["header"]["number"] - end - - block["transactions"].each do |tx| - ImportTransactionJob.perform_later tx, { block_hash: block["hash"] } - end - end -end diff --git a/app/jobs/import_transaction_job.rb b/app/jobs/import_transaction_job.rb deleted file mode 100644 index 3eac63c4e..000000000 --- a/app/jobs/import_transaction_job.rb +++ /dev/null @@ -1,335 +0,0 @@ -# process a raw transaction and save related records to database -class ImportTransactionJob < ApplicationJob - queue_as :default - attr_accessor :tx, :txid, :sdk_tx, :cell_dependencies_attrs, - :by_type_hash, :by_data_hash, - :deployed_cells_attrs, - :addresses, - :address_changes - - # @param tx_hash [String] - def perform(tx_hash, extra_data = {}) - self.address_changes = {} - if tx_hash.is_a?(Hash) - CkbTransaction.write_raw_hash_cache tx_hash["hash"], tx_hash - tx_hash = tx_hash["hash"] - end - @tx = CkbTransaction.unscoped.create_with(tx_status: :pending).find_or_create_by!(tx_hash:) - return unless tx.tx_pending? - - Rails.logger.info "Importing #{tx.tx_hash}" - @sdk_tx = CkbTransaction.fetch_sdk_transaction(tx_hash) - unless @sdk_tx - Rails.logger.info "Cannot fetch transaction details for #{tx_hash}" - return - end - @tx.cycles = extra_data[:cycles] - if extra_data[:timestamp] - @tx.created_at = Time.at(extra_data[:timestamp].to_d / 1000).utc - end - @tx.transaction_fee = extra_data[:fee] - @tx.bytes = extra_data[:size] || @sdk_tx.serialized_size_in_block - @tx.version = @sdk_tx.version - @tx.live_cell_changes = sdk_tx.outputs.count - sdk_tx.inputs.count - if extra_data[:block_hash] - block = Block.find_by block_hash: extra_data["block_hash"] - @tx.included_block_ids << block.id - end - @tx.save - @txid = tx.id - @deployed_cells_attrs = [] - @cell_dependencies_attrs = [] - @by_type_hash = {} - @by_data_hash = {} - - capacity_involved = 0 - - # process inputs - sdk_tx.inputs.each_with_index do |input, index| - if input.previous_output.tx_hash == CellOutput::SYSTEM_TX_HASH - tx.cell_inputs.create_with( - index:, - ).create_or_find_by( - previous_cell_output_id: nil, - from_cell_base: true, - ) - else - cell = CellOutput.find_by( - tx_hash: input.previous_output.tx_hash, - cell_index: input.previous_output.index, - ) - - if cell - process_input tx.cell_inputs.create_with( - previous_cell_output_id: cell.id, - ).create_or_find_by!( - ckb_transaction_id: txid, - index:, - ) - process_deployed_cell(cell.lock_script) - process_deployed_cell(cell.type_script) if cell.type_script - capacity_involved += cell.capacity - else - tx.cell_inputs.create_or_find_by!( - previous_tx_hash: input.previous_output.tx_hash, - previous_index: input.previous_output.index, - since: input.since, - index:, - ) - puts "Missing input #{input.previous_output.to_h} in #{tx_hash}" - # cannot find corresponding cell output, - # maybe the transaction contains the cell output has not been processed, - # so add current transaction to pending list, and wait for future processing - - list = Kredis.unique_list "pending_transactions_for_input:#{input.previous_output.tx_hash}" - list << tx_hash - end - end - end - @tx.update_column :capacity_involved, capacity_involved - # process outputs - sdk_tx.outputs.each_with_index do |output, index| - output_data = sdk_tx.outputs_data[index] - lock = LockScript.process(output.lock) - t = TypeScript.process(output.type) if output.type - cell = tx.cell_outputs.find_or_create_by( - tx_hash:, - cell_index: index, - ) - - # after the cell is created, create a datum - if output_data.present? && output_data != "0x" - (cell.cell_datum || cell.build_cell_datum).update(data: [output_data[2..]].pack("H*")) - end - - cell.lock_script = lock - cell.type_script = t - cell.update!( - address_id: lock.address_id, - capacity: output.capacity, - occupied_capacity: cell.calculate_min_capacity, - status: "pending", - ) - puts "output cell created tx_hash: #{tx_hash}, index: #{index}, cell_id: #{cell.id}" - - process_output cell - process_deployed_cell(cell.lock_script) - process_deployed_cell(cell.type_script) if cell.type_script - end - - process_cell_deps - process_header_deps - process_witnesses - save_relationship - save_changes - - # notify pending transaction to reprocess again - pending_list = Kredis.unique_list "pending_transactions_for_input:#{tx_hash}" - pending_list.elements.each do |_tx| - ImportTransactionJob.perform_later _tx - end - pending_list.clear - end - - def parse_code_dep(cell_dep) - # this cell output is the contract cell, i.e. one of deployed cells of the contract - cell_output = CellOutput.find_by_pointer cell_dep["out_point"]["tx_hash"], cell_dep["out_point"]["index"] - - attr = { - contract_cell_id: cell_output.id, - dep_type: cell_dep["dep_type"], - ckb_transaction_id: ckb_transaction.id, - # check if we already known the relationship between the contract cell and contract - contract_id: DeployedCell.cell_output_id_to_contract_id(cell_output.id), - implicit: cell_dep["implicit"] || false, - } - - # we don't know how the cells in transaction may refer to the contract cell - # so we make index for both `data` and `type` of `hash_type` - cell_output.data_hash ||= CKB::Blake2b.hexdigest(cell_output.binary_data) - - ## data type refer by the hash value of data field of cell - by_data_hash[cell_output.data_hash] = attr - - ## `type` type refer by the hash value of type field of cell - if cell_output.type_script_id - cell_output.type_hash ||= cell_output.type_script.script_hash - by_type_hash[cell_output.type_hash] = attr - end - - cell_output.save if cell_output.changed? # save data_hash type_hash to cell_output - cell_dependencies_attrs << attr - cell_output - end - - def save_relationship - @deployed_cells_attrs = deployed_cells_attrs.uniq { |a| a[:cell_output_id] } - if cell_dependencies_attrs.present? - CellDependency.upsert_all cell_dependencies_attrs.uniq { |a| - a[:contract_cell_id] - }, unique_by: %i[ckb_transaction_id contract_cell_id] - end - DeployedCell.upsert_all deployed_cells_attrs, unique_by: [:cell_output_id] if deployed_cells_attrs.present? - deployed_cells_attrs.each do |deployed_cell_attr| - DeployedCell.write_cell_output_id_to_contract_id( - deployed_cell_attr[:cell_output_id], - deployed_cell_attr[:contract_id], - ) - end - end - - def process_deployed_cell(lock_script_or_type_script) - @processed_script_for_deployed_cell ||= Set.new - return if @processed_script_for_deployed_cell.include?(lock_script_or_type_script) - - @processed_script_for_deployed_cell << lock_script_or_type_script - - dep = - case lock_script_or_type_script.hash_type - when "data", "data1", "data2" - by_data_hash[lock_script_or_type_script.code_hash] - when "type" - by_type_hash[lock_script_or_type_script.code_hash] - end - return unless dep - - unless dep[:contract_id] # we don't know the corresponding contract - contract = Contract.find_or_initialize_by code_hash: lock_script_or_type_script.code_hash, - hash_type: lock_script_or_type_script.hash_type - - if contract.id.blank? # newly created contract record - contract.deployed_args = lock_script_or_type_script.args - contract.role = lock_script_or_type_script.class.name - contract.save! - end - dep[:contract_id] = contract.id - - deployed_cells_attrs << { - contract_id: contract.id, - cell_output_id: dep[:contract_cell_id], - } - end - end - - def process_cell_deps - sdk_tx.cell_deps.each_with_index do |cell_dep, _index| - process_cell_dep cell_dep - end - end - - def process_cell_dep(cell_dep) - cell_dep = cell_dep.to_h if cell_dep.is_a?(CKB::Types::CellDep) - case cell_dep["dep_type"] - when "code" - parse_code_dep(cell_dep) - 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, - contract_id: nil, - implicit: false, - } - 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<") - # contract_cell = CellOutput.find_by_pointer "0x#{tx_hash}", cell_index - - parse_code_dep( - "out_point" => { - "tx_hash" => "0x#{tx_hash}", - "index" => cell_index, - }, - "dep_type" => "code", - "implicit" => true, # this is an implicit dependency - ) - end - end - end - - def process_header_deps - header_deps_attrs = [] - sdk_tx.header_deps.each_with_index do |header_dep, index| - header_deps_attrs << { - ckb_transaction_id: txid, - index:, - header_hash: header_dep, - } - end - if header_deps_attrs.present? - HeaderDependency.upsert_all(header_deps_attrs, - unique_by: %i[ckb_transaction_id index]) - end - end - - def process_witnesses - witnesses_attrs = [] - sdk_tx.witnesses.each_with_index do |w, i| - witnesses_attrs << { - ckb_transaction_id: txid, - index: i, - data: w, - } - end - if witnesses_attrs.present? - Witness.upsert_all(witnesses_attrs, unique_by: %i[ckb_transaction_id index]) - end - end - - # calculate address and balance change for each cell output - # @param cell_input [CellInput] - def process_input(cell_input) - cell_output = cell_input.previous_cell_output - - address_id = cell_output.address_id - changes = address_changes[address_id] ||= - { - balance: 0, - balance_occupied: 0, - } - changes[:balance] -= cell_output.capacity - changes[:balance_occupied] -= cell_output.occupied_capacity if cell_output.occupied_capacity - end - - # # calculate address and balance change for each cell output - # @param cell_output [CellOutput] - def process_output(cell_output) - address_id = cell_output.address_id - changes = address_changes[address_id] ||= - { - balance: 0, - balance_occupied: 0, - } - changes[:balance] += cell_output.capacity - changes[:balance_occupied] += cell_output.occupied_capacity - end - - def save_changes - if address_changes.present? - attrs = - address_changes.map do |address_id, c| - { - address_id:, - ckb_transaction_id: txid, - changes: c, - } - end - TransactionAddressChange.upsert_all( - attrs, - unique_by: %i[address_id ckb_transaction_id], - on_duplicate: Arel.sql( - "changes = transaction_address_changes.changes || excluded.changes", - ), - ) - AccountBook.upsert_all address_changes.keys.map { |address_id| { ckb_transaction_id: tx.id, address_id: } } - end - end -end diff --git a/app/jobs/revert_block_job.rb b/app/jobs/revert_block_job.rb index e1e49c928..54e3de4ab 100644 --- a/app/jobs/revert_block_job.rb +++ b/app/jobs/revert_block_job.rb @@ -31,7 +31,6 @@ def perform(local_tip_block = nil) benchmark :recalculate_udt_accounts, udt_type_hashes, local_tip_block benchmark :update_address_balance_and_ckb_transactions_count, local_tip_block benchmark :revert_block_rewards, local_tip_block - benchmark :revert_referring_cells, local_tip_block ForkedEvent.create!(block_number: local_tip_block.number, epoch_number: local_tip_block.epoch, block_timestamp: local_tip_block.timestamp) ApplicationRecord.benchmark "BlockStatisticGenerator" do @@ -208,9 +207,4 @@ def decrease_records_count(local_tip_block) normal_transactions = local_tip_block.ckb_transactions.normal ckb_transaction_counter.decrement!(:count, normal_transactions.count) if normal_transactions.present? end - - def revert_referring_cells(local_tip_block) - tx_ids = local_tip_block.ckb_transaction_ids - ReferringCell.where(ckb_transaction_id: tx_ids).delete_all - end end diff --git a/app/models/cell_output.rb b/app/models/cell_output.rb index d86a22b05..53eda33ef 100644 --- a/app/models/cell_output.rb +++ b/app/models/cell_output.rb @@ -42,8 +42,6 @@ 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 # 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 diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index bebdd415d..c68679762 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -93,7 +93,6 @@ def process_block(node_block, refresh_balance: true) async_update_udt_infos(local_block) flush_inputs_outputs_caches(local_block) generate_statistics_data(local_block) - # generate_deployed_cells_and_referring_cells(local_block) detect_cota_infos(local_block) detect_token_transfer(token_transfer_ckb_tx_ids) detect_bitcoin_transactions(local_block) @@ -122,10 +121,6 @@ def check_invalid_address(address) private - def generate_deployed_cells_and_referring_cells(local_block) - GenerateCellDependenciesWorker.perform_async(local_block.id) - end - def generate_statistics_data(local_block) GenerateStatisticsDataWorker.perform_async(local_block.id) end @@ -794,51 +789,14 @@ def build_cells_and_locks!( input_capacities = [] output_capacities = [] lock_scripts_attributes, type_scripts_attributes = build_scripts(outputs) - lock_script_ids = [] - type_script_ids = [] - if lock_scripts_attributes.present? - lock_scripts_attributes.map! do |attr| - attr.merge!(created_at: Time.current, updated_at: Time.current) - end - LockScript.upsert_all(lock_scripts_attributes, unique_by: :script_hash, returning: [:id]) - - # lock_script_ids.each do |row| - # lock_script_id = row["id"] - # lock_script = LockScript.find lock_script_id - # contract = Contract.find_by code_hash: lock_script.code_hash - # temp_hash = { script_hash: lock_script&.script_hash, is_contract: false } - # if contract - # temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id - # else - # contract = Contract.create code_hash: lock_script.script_hash - # temp_hash = temp_hash.merge contract_id: contract.id - # end - # # script = Script.find_or_create_by temp_hash - # # lock_script.update script_id: script.id - # end + if lock_scripts_attributes.any? + LockScript.upsert_all(lock_scripts_attributes, unique_by: :script_hash, returning: [:id], record_timestamps: true) end - - if type_scripts_attributes.present? - type_scripts_attributes.map! do |attr| - attr.merge!(created_at: Time.current, updated_at: Time.current) - end - TypeScript.upsert_all(type_scripts_attributes, unique_by: :script_hash, returning: [:id]) - # type_script_ids.each do |row| - # type_script_id = row["id"] - # type_script = TypeScript.find(type_script_id) - # temp_hash = { script_hash: type_script&.script_hash, is_contract: false } - # contract = Contract.find_by code_hash: type_script.code_hash - # if contract - # temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id - # else - # contract = Contract.create code_hash: type_script.script_hash - # temp_hash = temp_hash.merge contract_id: contract.id - # end - # # script = Script.find_or_create_by temp_hash - # # type_script.update script_id: script.id - # end + if type_scripts_attributes.any? + TypeScript.upsert_all(type_scripts_attributes, unique_by: :script_hash, returning: [:id], record_timestamps: true) end + build_addresses!(outputs, local_block) # prepare script ids for insert cell_outputs prepare_script_ids(outputs) @@ -910,9 +868,6 @@ def build_cells_and_locks!( record_timestamps: true) end - # ScriptTransaction.create_from_scripts TypeScript.where(id: type_script_ids) - # ScriptTransaction.create_from_scripts LockScript.where(id: lock_script_ids) - [input_capacities, output_capacities] end diff --git a/app/models/ckb_transaction.rb b/app/models/ckb_transaction.rb index a8ba683a1..ef86f1dd9 100644 --- a/app/models/ckb_transaction.rb +++ b/app/models/ckb_transaction.rb @@ -24,11 +24,8 @@ class CkbTransaction < ApplicationRecord accepts_nested_attributes_for :cell_outputs has_many :inputs, class_name: "CellOutput", inverse_of: "consumed_by", foreign_key: "consumed_by_id" has_many :outputs, class_name: "CellOutput" - has_many :dao_events # , dependent: :delete_all - # has_many :script_transactions, dependent: :delete_all - # has_many :scripts, through: :script_transactions + has_many :dao_events - has_many :referring_cells has_many :token_transfers, foreign_key: :transaction_id, inverse_of: :ckb_transaction has_many :cell_dependencies has_many :header_dependencies diff --git a/app/models/deployed_cell.rb b/app/models/deployed_cell.rb deleted file mode 100644 index 3cdf5fec5..000000000 --- a/app/models/deployed_cell.rb +++ /dev/null @@ -1,195 +0,0 @@ -class DeployedCell < ApplicationRecord - belongs_to :contract - belongs_to :cell_output - # one contract can has multiple deployed cells - validates :cell_output, uniqueness: true - - # find the corresponding contract defined in the specified cell output via cache - # @param cell_output_id [Integer] deployed cell output id - def self.cell_output_id_to_contract_id(cell_output_id) - Rails.cache.fetch(["cell_output_id_to_contract_id", cell_output_id], expires_in: 1.day) do - DeployedCell.where(cell_output_id:).pick(:contract_id) - end - end - - # save the contract <-> deployed cell mapping to cache - # @param cell_output_id [Integer] deployed cell output id - # @param contract_id [Integer] contract id - def self.write_cell_output_id_to_contract_id(cell_output_id, contract_id) - Rails.cache.write(["cell_output_id_to_contract_id", cell_output_id], contract_id, expires_in: 1.day) - end - - # create initial data for this table - # before running this method, - # 1. run Script.create_initial_data - # 2. run this method: DeployedCell.create_initial_data - def self.create_initial_data(ckb_transaction_id = 0) - Rails.logger.info "=== ckb_transaction_id: #{ckb_transaction_id.inspect}" - pool = Concurrent::FixedThreadPool.new(5, max_queue: 1000, - fallback_policy: :caller_runs) - CkbTransaction.tx_committed.where(is_cellbase: false).where("id >= ?", - ckb_transaction_id).find_each do |ckb_transaction| - Rails.logger.info "=== ckb_transaction: #{ckb_transaction.id}" - # pool.post do - Rails.application.executor.wrap do - ActiveRecord::Base.connection_pool.with_connection do - ActiveRecord::Base.cache do - if ckb_transaction.cell_dependencies.empty? - puts ckb_transaction.raw_hash["cell_deps"] - DeployedCell.create_initial_data_for_ckb_transaction ckb_transaction, - ckb_transaction.raw_hash["cell_deps"] - end - end - end - end - # end - end - pool.shutdown - pool.wait_for_termination - Rails.logger.info "== done" - end - - def self.create_initial_data_for_ckb_transaction(ckb_transaction, cell_deps) - return if cell_deps.blank? - - deployed_cells = [] - cell_dependencies_attrs = [] - by_type_hash = {} - by_data_hash = {} - - # initialize cell dependencies records - # the `cell_deps` field in ckb transactions stores the contract cell (referred by out point, - # which contains the compiled byte code of contract) the transaction should refer. - # the submitter of the transaction is responsible for including all the contract cells - # specified by all the `type_script` and `lock_script` of the cell inputs and cell outputs - - parse_code_dep = - ->(cell_dep) do - # this cell output is the contract cell, i.e. one of deployed cells of the contract - cell_output = CellOutput.find_by_pointer cell_dep["out_point"]["tx_hash"], cell_dep["out_point"]["index"] - - attr = { - contract_cell_id: cell_output.id, - dep_type: cell_dep["dep_type"], - ckb_transaction_id: ckb_transaction.id, - contract_id: DeployedCell.cell_output_id_to_contract_id(cell_output.id), # check if we already known the relationship between the contract cell and contract - implicit: cell_dep["implicit"] || false, - } - - # we don't know how the cells in transaction may refer to the contract cell - # so we make index for both `data` and `type` of `hash_type` - cell_output.data_hash ||= CKB::Blake2b.hexdigest(cell_output.binary_data) if cell_output.binary_data - - by_data_hash[cell_output.data_hash] = attr # data type refer by the hash value of data field of cell - # `type` type refer by the hash value of type field of cell - if cell_output.type_script_id - cell_output.type_hash ||= cell_output.type_script.script_hash - by_type_hash[cell_output.type_hash] = attr - end - cell_output.save if cell_output.changed? # save data_hash type_hash to cell_output - cell_dependencies_attrs << attr - cell_output - end - - 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" - parse_code_dep[cell_dep] - 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, - contract_id: nil, - implicit: false, - } - 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<") - out_points = [] - # 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<") - # contract_cell = CellOutput.find_by_pointer "0x#{tx_hash}", cell_index - - co = parse_code_dep[{ - "out_point" => { - "tx_hash" => "0x#{tx_hash}", - "index" => cell_index, - }, - "dep_type" => "code", - "implicit" => true, # this is an implicit dependency - }] - end - end - end - - cells = ckb_transaction.cell_outputs.includes(:lock_script, :type_script).to_a + - ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output) - scripts = cells.compact.inject([]) { |a, cell| a + [cell.lock_script, cell.type_script] }.compact.uniq - deployed_cells_attrs = [] - - scripts.each do |lock_script_or_type_script| - dep = - case lock_script_or_type_script.hash_type - when "data", "data1", "data2" - by_data_hash[lock_script_or_type_script.code_hash] - when "type" - by_type_hash[lock_script_or_type_script.code_hash] - end - next unless dep - - unless dep[:contract_id] # we don't know the corresponding contract - contract = Contract.find_or_initialize_by code_hash: lock_script_or_type_script.code_hash, - hash_type: lock_script_or_type_script.hash_type - - if contract.id.blank? # newly created contract record - contract.deployed_args = lock_script_or_type_script.args - contract.role = lock_script_or_type_script.class.name - contract.save! - end - dep[:contract_id] = contract.id - - deployed_cells_attrs << { - contract_id: contract.id, - cell_output_id: dep[:contract_cell_id], - } - end - end - - deployed_cells_attrs = deployed_cells_attrs.uniq { |a| a[:cell_output_id] } - - if cell_dependencies_attrs.present? - CellDependency.upsert_all cell_dependencies_attrs.uniq { |a| - a[:contract_cell_id] - }, unique_by: %i[ckb_transaction_id contract_cell_id] - end - DeployedCell.upsert_all deployed_cells_attrs, unique_by: [:cell_output_id] if deployed_cells_attrs.present? - deployed_cells_attrs.each do |deployed_cell_attr| - DeployedCell.write_cell_output_id_to_contract_id(deployed_cell_attr[:cell_output_id], - deployed_cell_attr[:contract_id]) - end - end -end - -# == Schema Information -# -# Table name: deployed_cells -# -# id :bigint not null, primary key -# cell_output_id :bigint not null -# contract_id :bigint not null -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# index_deployed_cells_on_cell_output_id (cell_output_id) UNIQUE -# index_deployed_cells_on_contract_id_and_cell_output_id (contract_id,cell_output_id) UNIQUE -# diff --git a/app/models/distribution_data.rb b/app/models/distribution_data.rb index da73c1367..bcc2d10eb 100644 --- a/app/models/distribution_data.rb +++ b/app/models/distribution_data.rb @@ -1,8 +1,7 @@ class DistributionData VALID_INDICATORS = %w( address_balance_distribution block_time_distribution epoch_time_distribution epoch_length_distribution - average_block_time nodes_distribution block_propagation_delay_history transaction_propagation_delay_history - miner_address_distribution + average_block_time nodes_distribution block_propagation_delay_history miner_address_distribution ).freeze def id @@ -55,28 +54,6 @@ def block_propagation_delay_history BlockPropagationDelay.connection.select_all(sql) end - def transaction_propagation_delay_history - round_num = 4 - sql = - <<-SQL - select created_at_unixtimestamp, - round(avg((durations->>0)::numeric), #{round_num}) avg5, round(avg((durations->>1)::numeric), #{round_num}) avg10, - round(avg((durations->>2)::numeric), #{round_num}) avg15, round(avg((durations->>3)::numeric), #{round_num}) avg20, - round(avg((durations->>4)::numeric), #{round_num}) avg25, round(avg((durations->>5)::numeric), #{round_num}) avg30, - round(avg((durations->>6)::numeric), #{round_num}) avg35, round(avg((durations->>7)::numeric), #{round_num}) avg40, - round(avg((durations->>8)::numeric), #{round_num}) avg45, round(avg((durations->>9)::numeric), #{round_num}) avg50, - round(avg((durations->>10)::numeric), #{round_num}) avg55, round(avg((durations->>11)::numeric), #{round_num}) avg60, - round(avg((durations->>12)::numeric), #{round_num}) avg65, round(avg((durations->>13)::numeric), #{round_num}) avg70, - round(avg((durations->>14)::numeric), #{round_num}) avg75, round(avg((durations->>15)::numeric), #{round_num}) avg80, - round(avg((durations->>16)::numeric), #{round_num}) avg85, round(avg((durations->>17)::numeric), #{round_num}) avg90 - from transaction_propagation_delays - group by created_at_unixtimestamp - order by created_at_unixtimestamp - SQL - - TransactionPropagationDelay.connection.select_all(sql) - end - def miner_address_distribution(checkpoint = 7) supported_checkpoints = [7, 90] return unless checkpoint.in?(supported_checkpoints) diff --git a/app/models/lock_script.rb b/app/models/lock_script.rb index 77984fb53..2445d2dbc 100644 --- a/app/models/lock_script.rb +++ b/app/models/lock_script.rb @@ -7,9 +7,6 @@ class LockScript < ApplicationRecord belongs_to :address, optional: true # will remove this later - belongs_to :script, optional: true - belongs_to :contract, optional: true, primary_key: "code_hash", foreign_key: "code_hash" - validates_presence_of :code_hash attribute :code_hash, :ckb_hash diff --git a/app/models/referring_cell.rb b/app/models/referring_cell.rb deleted file mode 100644 index 2deaba7d1..000000000 --- a/app/models/referring_cell.rb +++ /dev/null @@ -1,61 +0,0 @@ -# TODO keep ReferringCell or CellDependency -# referring cells v2. -class ReferringCell < ApplicationRecord - belongs_to :contract - belongs_to :ckb_transaction - belongs_to :cell_output - - # create initial data - # please run this script - def self.create_initial_data(ckb_transaction_id = nil) - CkbTransaction.where("id <= ?", ckb_transaction_id).find_each do |ckb_transaction| - self.create_initial_data_for_ckb_transaction ckb_transaction - end - end - - def self.create_initial_data_for_ckb_transaction(ckb_transaction) - inputs = ckb_transaction.inputs - outputs = ckb_transaction.outputs - - (inputs + outputs).each do |cell| - contracts = [cell.lock_script.contract, cell.type_script&.contract].compact - - next if contracts.empty? - - contracts.each do |contract| - if cell.live? - ReferringCell.create_or_find_by( - cell_output_id: cell.id, - ckb_transaction_id: ckb_transaction.id, - contract_id: contract.id - ) - elsif cell.dead? - referring_cell = ReferringCell.find_by( - cell_output_id: cell.id, - ckb_transaction_id: ckb_transaction.id, - contract_id: contract.id - ) - - referring_cell.destroy if referring_cell - end - end - end - end -end - -# == Schema Information -# -# Table name: referring_cells -# -# id :bigint not null, primary key -# cell_output_id :bigint -# contract_id :bigint -# ckb_transaction_id :bigint -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# index_referring_cells_on_cell_output_id (cell_output_id) UNIQUE -# index_referring_cells_on_contract_id_and_cell_output_id (contract_id,cell_output_id) UNIQUE -# diff --git a/app/models/script.rb b/app/models/script.rb deleted file mode 100644 index 12a5f00ec..000000000 --- a/app/models/script.rb +++ /dev/null @@ -1,58 +0,0 @@ -class Script < ActiveRecord::Base - has_many :lock_scripts - has_many :type_scripts - has_many :cell_dependencies - - has_many :script_transactions - has_many :ckb_transactions, through: :script_transactions - - belongs_to :contract, optional: true - - def self.create_initial_data - contracts = {} - Contract.all.each do |contract| - contracts[contract.code_hash] = contract - end - TypeScript.find_each do |type_script| - contract_id = contracts[type_script.code_hash]&.id - - temp_hash = { args: type_script.args, script_hash: type_script.script_hash, is_contract: false } - if contract_id - temp_hash = temp_hash.merge is_contract: true, contract_id: contract_id - end - - script = Script.find_or_create_by temp_hash - type_script.update script_id: script.id - end - - LockScript.find_each do |lock_script| - contract_id = contracts[lock_script.code_hash]&.id - - temp_hash = { args: lock_script.args, script_hash: lock_script.script_hash, is_contract: false } - if contract_id - temp_hash = temp_hash.merge is_contract: true, contract_id: contract_id - end - script = Script.find_or_create_by temp_hash - lock_script.update script_id: script.id - end - - Rails.logger.info "== Script.create_initial_data done" - end -end - -# == Schema Information -# -# Table name: scripts -# -# id :bigint not null, primary key -# args :string -# script_hash :string -# is_contract :boolean default(FALSE) -# contract_id :bigint -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# index_scripts_on_contract_id (contract_id) -# diff --git a/app/models/script_transaction.rb b/app/models/script_transaction.rb deleted file mode 100644 index 98f011976..000000000 --- a/app/models/script_transaction.rb +++ /dev/null @@ -1,73 +0,0 @@ -class ScriptTransaction < ApplicationRecord - belongs_to :script - belongs_to :ckb_transaction - - # run these methods: - # ScriptTransaction.create_initial_data - def self.create_initial_data - connection.execute <<-SQL - insert into script_transactions (ckb_transaction_id, script_id) - select co.ckb_transaction_id, ls.script_id from cell_outputs co inner join lock_scripts ls on co.lock_script_id = ls.id where ls.script_id is not null - on conflict do nothing - SQL - - connection.execute <<-SQL - insert into script_transactions (ckb_transaction_id, script_id) - select co.ckb_transaction_id, ts.script_id from cell_outputs co inner join type_scripts ts on co.type_script_id = ts.id where ts.script_id is not null - on conflict do nothing - SQL - end - - def self.create_from_scripts(type_scripts_or_lock_scripts) - ls_ids = [] - ts_ids = [] - type_scripts_or_lock_scripts.each do |s| - if s.is_a?(TypeScript) - ts_ids << s.id - else - ls_ids << s.id - end - end - if ls_ids.present? - connection.execute <<-SQL - insert into script_transactions (ckb_transaction_id, script_id) - select ckb_transaction_id, script_id from lock_scripts ls - inner join ( - select co.ckb_transaction_id, co.lock_script_id - from cell_outputs co - where co.lock_script_id in (#{ls_ids.join(',')}) - ) as tmp on ls.id = tmp.lock_script_id - where ls.script_id is not null - on conflict do nothing - SQL - end - if ts_ids.present? - connection.execute <<-SQL - insert into script_transactions (ckb_transaction_id, script_id) - select ckb_transaction_id, script_id from type_scripts ts - inner join ( - select co.ckb_transaction_id, co.type_script_id - from cell_outputs co - where co.type_script_id in (#{ts_ids.join(',')}) - ) as tmp on ts.id = tmp.type_script_id - where ts.script_id is not null - on conflict do nothing - SQL - end - end -end - -# == Schema Information -# -# Table name: script_transactions -# -# id :bigint not null, primary key -# script_id :bigint not null -# ckb_transaction_id :bigint not null -# -# Indexes -# -# index_script_transactions_on_ckb_transaction_id (ckb_transaction_id) -# index_script_transactions_on_ckb_transaction_id_and_script_id (ckb_transaction_id,script_id) UNIQUE -# index_script_transactions_on_script_id (script_id) -# diff --git a/app/models/transaction_propagation_delay.rb b/app/models/transaction_propagation_delay.rb deleted file mode 100644 index 24b2c554c..000000000 --- a/app/models/transaction_propagation_delay.rb +++ /dev/null @@ -1,18 +0,0 @@ -class TransactionPropagationDelay < ApplicationRecord -end - -# == Schema Information -# -# Table name: transaction_propagation_delays -# -# id :bigint not null, primary key -# tx_hash :string -# created_at_unixtimestamp :integer -# durations :jsonb -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# index_tx_propagation_timestamp (created_at_unixtimestamp) -# diff --git a/app/models/type_script.rb b/app/models/type_script.rb index c0173ea2f..b4ee0db07 100644 --- a/app/models/type_script.rb +++ b/app/models/type_script.rb @@ -4,9 +4,6 @@ class TypeScript < ApplicationRecord belongs_to :cell_output, optional: true # will remove this later before_validation :generate_script_hash - belongs_to :script, optional: true - belongs_to :contract, optional: true, primary_key: "code_hash", foreign_key: "code_hash" - validates_presence_of :code_hash attribute :code_hash, :ckb_hash diff --git a/app/serializers/scripts_ckb_transactions_serializer.rb b/app/serializers/scripts_ckb_transactions_serializer.rb deleted file mode 100644 index 09a718b45..000000000 --- a/app/serializers/scripts_ckb_transactions_serializer.rb +++ /dev/null @@ -1,29 +0,0 @@ -class ScriptsCkbTransactionsSerializer - include FastJsonapi::ObjectSerializer - - def to_json(tx) - { - id: tx.id, - tx_hash: tx.tx_hash, - block_id: tx.block_id, - block_number: tx.block_number, - block_timestamp: tx.block_timestamp, - transaction_fee: tx.transaction_fee, - is_cellbase: tx.is_cellbase, - header_deps: tx.header_deps, - cell_deps: tx.cell_deps, - witnesses: tx.witnesses, - live_cell_changes: tx.live_cell_changes, - capacity_involved: tx.capacity_involved, - contained_address_ids: tx.contained_address_ids, - tags: tx.tags, - contained_udt_ids: tx.contained_udt_ids, - dao_address_ids: tx.contained_dao_address_ids, - udt_address_ids: tx.contained_udt_address_ids, - bytes: tx.bytes, - tx_status: tx.tx_status, - display_inputs: tx.display_inputs, - display_outputs: tx.display_outputs - } - end -end diff --git a/app/views/api/v2/scripts/deployed_cells.json.jbuilder b/app/views/api/v2/scripts/deployed_cells.json.jbuilder deleted file mode 100644 index ddf21033d..000000000 --- a/app/views/api/v2/scripts/deployed_cells.json.jbuilder +++ /dev/null @@ -1,29 +0,0 @@ -json.data do - json.deployed_cells @deployed_cells do |deployed_cell| - json.id deployed_cell.id - json.capacity deployed_cell.capacity - json.ckb_transaction_id deployed_cell.ckb_transaction_id - json.created_at deployed_cell.created_at - json.updated_at deployed_cell.updated_at - json.status deployed_cell.status - json.address_id deployed_cell.address_id - json.block_id deployed_cell.block_id - json.tx_hash deployed_cell.tx_hash - json.cell_index deployed_cell.cell_index - json.consumed_by_id deployed_cell.consumed_by_id - json.cell_type deployed_cell.cell_type - json.data_size deployed_cell.data_size - json.occupied_capacity deployed_cell.occupied_capacity - json.block_timestamp deployed_cell.block_timestamp - json.consumed_block_timestamp deployed_cell.consumed_block_timestamp - json.type_hash deployed_cell.type_hash - json.udt_amount deployed_cell.udt_amount - json.dao deployed_cell.dao - json.lock_script_id deployed_cell.lock_script_id - json.type_script_id deployed_cell.type_script_id - end - json.meta do - json.total @deployed_cells.total_count - json.page_size @page_size.to_i - end -end diff --git a/app/views/api/v2/scripts/referring_cells.json.jbuilder b/app/views/api/v2/scripts/referring_cells.json.jbuilder deleted file mode 100644 index c496c2e9e..000000000 --- a/app/views/api/v2/scripts/referring_cells.json.jbuilder +++ /dev/null @@ -1,29 +0,0 @@ -json.data do - json.referring_cells @referring_cells do |referring_cell| - json.id referring_cell.id - json.capacity referring_cell.capacity - json.ckb_transaction_id referring_cell.ckb_transaction_id - json.created_at referring_cell.created_at - json.updated_at referring_cell.updated_at - json.status referring_cell.status - json.address_id referring_cell.address_id - json.block_id referring_cell.block_id - json.tx_hash referring_cell.tx_hash - json.cell_index referring_cell.cell_index - json.consumed_by_id referring_cell.consumed_by_id - json.cell_type referring_cell.cell_type - json.data_size referring_cell.data_size - json.occupied_capacity referring_cell.occupied_capacity - json.block_timestamp referring_cell.block_timestamp - json.consumed_block_timestamp referring_cell.consumed_block_timestamp - json.type_hash referring_cell.type_hash - json.udt_amount referring_cell.udt_amount - json.dao referring_cell.dao - json.lock_script_id referring_cell.lock_script_id - json.type_script_id referring_cell.type_script_id - end - json.meta do - json.total @referring_cells.total_count - json.page_size @page_size.to_i - end -end diff --git a/app/workers/generate_cell_dependencies_worker.rb b/app/workers/generate_cell_dependencies_worker.rb deleted file mode 100644 index fb528d261..000000000 --- a/app/workers/generate_cell_dependencies_worker.rb +++ /dev/null @@ -1,20 +0,0 @@ -class GenerateCellDependenciesWorker - include Sidekiq::Worker - - def perform(block_id) - block = Block.find_by(id: block_id) - return unless block - - tx_cell_deps = build_cell_deps(block.number) - block.ckb_transactions.each do |txs| - CellDependency.parse_cell_dpes_from_ckb_transaction(txs, tx_cell_deps[txs.tx_hash]) - end - end - - def build_cell_deps(number) - node_block = CkbSync::Api.instance.get_block_by_number(number) - node_block.transactions.each_with_object({}) do |tx, deps| - deps[tx.hash] = tx.cell_deps - end - end -end diff --git a/app/workers/pool_transaction_check_worker.rb b/app/workers/pool_transaction_check_worker.rb index e6ce84869..5d06b030b 100644 --- a/app/workers/pool_transaction_check_worker.rb +++ b/app/workers/pool_transaction_check_worker.rb @@ -24,10 +24,6 @@ def perform tx.create_reject_reason!(message: "unknown") end end - - if reason["status"] == "committed" && CkbTransaction.where(tx_hash: tx.tx_hash).count == 2 && CkbTransaction.where(tx_hash: tx.tx_hash, tx_status: :committed).exists? - tx.destroy - end end end end diff --git a/db/migrate/20241205023729_drop_scripts_and_scripts_transactions.rb b/db/migrate/20241205023729_drop_scripts_and_scripts_transactions.rb new file mode 100644 index 000000000..a37b268ae --- /dev/null +++ b/db/migrate/20241205023729_drop_scripts_and_scripts_transactions.rb @@ -0,0 +1,9 @@ +class DropScriptsAndScriptsTransactions < ActiveRecord::Migration[7.0] + def change + drop_table :scripts, if_exists: true + drop_table :script_transactions, if_exists: true + drop_table :deployed_cells, if_exists: true + drop_table :referring_cells, if_exists: true + drop_table :transaction_propagation_delays, if_exists: true + end +end diff --git a/db/structure.sql b/db/structure.sql index b1b2bedbb..c1f18c9b6 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1673,38 +1673,6 @@ CREATE SEQUENCE public.dao_events_id_seq ALTER SEQUENCE public.dao_events_id_seq OWNED BY public.dao_events.id; --- --- Name: deployed_cells; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.deployed_cells ( - id bigint NOT NULL, - cell_output_id bigint NOT NULL, - contract_id bigint NOT NULL, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - --- --- Name: deployed_cells_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.deployed_cells_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: deployed_cells_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.deployed_cells_id_seq OWNED BY public.deployed_cells.id; - - -- -- Name: epoch_statistics; Type: TABLE; Schema: public; Owner: - -- @@ -2346,39 +2314,6 @@ CREATE SEQUENCE public.portfolios_id_seq ALTER SEQUENCE public.portfolios_id_seq OWNED BY public.portfolios.id; --- --- Name: referring_cells; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.referring_cells ( - id bigint NOT NULL, - cell_output_id bigint, - contract_id bigint, - ckb_transaction_id bigint, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - --- --- Name: referring_cells_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.referring_cells_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: referring_cells_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.referring_cells_id_seq OWNED BY public.referring_cells.id; - - -- -- Name: reject_reasons; Type: TABLE; Schema: public; Owner: - -- @@ -2430,70 +2365,6 @@ CREATE TABLE public.schema_migrations ( ); --- --- Name: script_transactions; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.script_transactions ( - id bigint NOT NULL, - script_id bigint NOT NULL, - ckb_transaction_id bigint NOT NULL -); - - --- --- Name: script_transactions_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.script_transactions_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: script_transactions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.script_transactions_id_seq OWNED BY public.script_transactions.id; - - --- --- Name: scripts; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.scripts ( - id bigint NOT NULL, - args character varying, - script_hash character varying, - is_contract boolean DEFAULT false, - contract_id bigint, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - --- --- Name: scripts_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.scripts_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: scripts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.scripts_id_seq OWNED BY public.scripts.id; - - -- -- Name: statistic_infos; Type: TABLE; Schema: public; Owner: - -- @@ -2716,39 +2587,6 @@ CREATE SEQUENCE public.transaction_address_changes_id_seq ALTER SEQUENCE public.transaction_address_changes_id_seq OWNED BY public.transaction_address_changes.id; --- --- Name: transaction_propagation_delays; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.transaction_propagation_delays ( - id bigint NOT NULL, - tx_hash character varying, - created_at_unixtimestamp integer, - durations jsonb, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - --- --- Name: transaction_propagation_delays_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.transaction_propagation_delays_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: transaction_propagation_delays_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.transaction_propagation_delays_id_seq OWNED BY public.transaction_propagation_delays.id; - - -- -- Name: type_scripts; Type: TABLE; Schema: public; Owner: - -- @@ -3344,13 +3182,6 @@ ALTER TABLE ONLY public.dao_contracts ALTER COLUMN id SET DEFAULT nextval('publi ALTER TABLE ONLY public.dao_events ALTER COLUMN id SET DEFAULT nextval('public.dao_events_id_seq'::regclass); --- --- Name: deployed_cells id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.deployed_cells ALTER COLUMN id SET DEFAULT nextval('public.deployed_cells_id_seq'::regclass); - - -- -- Name: epoch_statistics id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3463,13 +3294,6 @@ ALTER TABLE ONLY public.omiga_inscription_infos ALTER COLUMN id SET DEFAULT next ALTER TABLE ONLY public.portfolios ALTER COLUMN id SET DEFAULT nextval('public.portfolios_id_seq'::regclass); --- --- Name: referring_cells id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.referring_cells ALTER COLUMN id SET DEFAULT nextval('public.referring_cells_id_seq'::regclass); - - -- -- Name: reject_reasons id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3477,20 +3301,6 @@ ALTER TABLE ONLY public.referring_cells ALTER COLUMN id SET DEFAULT nextval('pub ALTER TABLE ONLY public.reject_reasons ALTER COLUMN id SET DEFAULT nextval('public.reject_reasons_id_seq'::regclass); --- --- Name: script_transactions id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.script_transactions ALTER COLUMN id SET DEFAULT nextval('public.script_transactions_id_seq'::regclass); - - --- --- Name: scripts id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.scripts ALTER COLUMN id SET DEFAULT nextval('public.scripts_id_seq'::regclass); - - -- -- Name: statistic_infos id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3533,13 +3343,6 @@ ALTER TABLE ONLY public.token_transfers ALTER COLUMN id SET DEFAULT nextval('pub ALTER TABLE ONLY public.transaction_address_changes ALTER COLUMN id SET DEFAULT nextval('public.transaction_address_changes_id_seq'::regclass); --- --- Name: transaction_propagation_delays id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.transaction_propagation_delays ALTER COLUMN id SET DEFAULT nextval('public.transaction_propagation_delays_id_seq'::regclass); - - -- -- Name: type_scripts id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3931,14 +3734,6 @@ ALTER TABLE ONLY public.dao_events ADD CONSTRAINT dao_events_pkey PRIMARY KEY (id); --- --- Name: deployed_cells deployed_cells_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.deployed_cells - ADD CONSTRAINT deployed_cells_pkey PRIMARY KEY (id); - - -- -- Name: epoch_statistics epoch_statistics_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4067,14 +3862,6 @@ ALTER TABLE ONLY public.portfolios ADD CONSTRAINT portfolios_pkey PRIMARY KEY (id); --- --- Name: referring_cells referring_cells_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.referring_cells - ADD CONSTRAINT referring_cells_pkey PRIMARY KEY (id); - - -- -- Name: reject_reasons reject_reasons_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4091,22 +3878,6 @@ ALTER TABLE ONLY public.schema_migrations ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); --- --- Name: script_transactions script_transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.script_transactions - ADD CONSTRAINT script_transactions_pkey PRIMARY KEY (id); - - --- --- Name: scripts scripts_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.scripts - ADD CONSTRAINT scripts_pkey PRIMARY KEY (id); - - -- -- Name: statistic_infos statistic_infos_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4155,14 +3926,6 @@ ALTER TABLE ONLY public.transaction_address_changes ADD CONSTRAINT transaction_address_changes_pkey PRIMARY KEY (id); --- --- Name: transaction_propagation_delays transaction_propagation_delays_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.transaction_propagation_delays - ADD CONSTRAINT transaction_propagation_delays_pkey PRIMARY KEY (id); - - -- -- Name: type_scripts type_scripts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -5134,20 +4897,6 @@ CREATE INDEX index_dao_events_on_block_timestamp ON public.dao_events USING btre CREATE INDEX index_dao_events_on_status_and_event_type ON public.dao_events USING btree (status, event_type); --- --- Name: index_deployed_cells_on_cell_output_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_deployed_cells_on_cell_output_id ON public.deployed_cells USING btree (cell_output_id); - - --- --- Name: index_deployed_cells_on_contract_id_and_cell_output_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_deployed_cells_on_contract_id_and_cell_output_id ON public.deployed_cells USING btree (contract_id, cell_output_id); - - -- -- Name: index_epoch_statistics_on_epoch_number; Type: INDEX; Schema: public; Owner: - -- @@ -5302,20 +5051,6 @@ CREATE INDEX index_on_cell_dependencies_contract_cell_block_tx ON public.cell_de CREATE UNIQUE INDEX index_portfolios_on_user_id_and_address_id ON public.portfolios USING btree (user_id, address_id); --- --- Name: index_referring_cells_on_cell_output_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_referring_cells_on_cell_output_id ON public.referring_cells USING btree (cell_output_id); - - --- --- Name: index_referring_cells_on_contract_id_and_cell_output_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_referring_cells_on_contract_id_and_cell_output_id ON public.referring_cells USING btree (contract_id, cell_output_id); - - -- -- Name: index_reject_reasons_on_ckb_transaction_id; Type: INDEX; Schema: public; Owner: - -- @@ -5330,34 +5065,6 @@ CREATE UNIQUE INDEX index_reject_reasons_on_ckb_transaction_id ON public.reject_ CREATE UNIQUE INDEX index_rolling_avg_block_time_on_timestamp ON public.rolling_avg_block_time USING btree ("timestamp"); --- --- Name: index_script_transactions_on_ckb_transaction_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_script_transactions_on_ckb_transaction_id ON public.script_transactions USING btree (ckb_transaction_id); - - --- --- Name: index_script_transactions_on_ckb_transaction_id_and_script_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_script_transactions_on_ckb_transaction_id_and_script_id ON public.script_transactions USING btree (ckb_transaction_id, script_id); - - --- --- Name: index_script_transactions_on_script_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_script_transactions_on_script_id ON public.script_transactions USING btree (script_id); - - --- --- Name: index_scripts_on_contract_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_scripts_on_contract_id ON public.scripts USING btree (contract_id); - - -- -- Name: index_table_record_counts_on_table_name_and_count; Type: INDEX; Schema: public; Owner: - -- @@ -5449,13 +5156,6 @@ CREATE INDEX index_token_transfers_on_transaction_id ON public.token_transfers U CREATE INDEX index_transaction_address_changes_on_ckb_transaction_id ON public.transaction_address_changes USING btree (ckb_transaction_id); --- --- Name: index_tx_propagation_timestamp; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_tx_propagation_timestamp ON public.transaction_propagation_delays USING btree (created_at_unixtimestamp); - - -- -- Name: index_type_scripts_on_cell_output_id; Type: INDEX; Schema: public; Owner: - -- @@ -6440,4 +6140,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20241125100650'), ('20241129000339'), ('20241129032447'), -('20241202072604'); +('20241202072604'), +('20241205023729'); + + diff --git a/lib/tasks/migration/generate_referring_cells.rake b/lib/tasks/migration/generate_referring_cells.rake deleted file mode 100644 index 9de2d6a81..000000000 --- a/lib/tasks/migration/generate_referring_cells.rake +++ /dev/null @@ -1,54 +0,0 @@ -namespace :migration do - desc "Usage: RAILS_ENV=production bundle exec rake migration:generate_referring_cells" - task generate_referring_cells: :environment do - live_cells = CellOutput.live.left_joins(:referring_cell).where(referring_cells: { id: nil }) - progress_bar = ProgressBar.create({ total: live_cells.count, - format: "%e %B %p%% %c/%C" }) - - live_cells.find_in_batches do |outputs| - outputs.each do |output| - progress_bar.increment - - contracts = [output.lock_script.contract, - output.type_script&.contract].compact - - next if contracts.empty? - - contracts.each do |contract| - ReferringCell.create_or_find_by( - cell_output_id: output.id, - ckb_transaction_id: output.ckb_transaction_id, - contract_id: contract.id, - ) - end - end - end - - puts "done" - end - - desc "Usage: RAILS_ENV=production bundle exec rake migration:generate_missed_type_script_contract_referring_cells" - task generate_missed_type_script_contract_referring_cells: :environment do - contract_hashes = Contract.where(role: "type_script").pluck(:code_hash) - binary_hashes = CkbUtils.hexes_to_bins_sql(contract_hashes) - contract_type_ids = TypeScript.where("code_hash IN (#{binary_hashes})").pluck(:id) - contract_type_ids.each do |type_id| - puts "============#{type_id}" - live_cells = CellOutput.live.where(type_script_id: type_id) - - live_cells.find_in_batches do |outputs| - outputs.each do |output| - contract = output.type_script&.contract - - ReferringCell.create_or_find_by( - cell_output_id: output.id, - ckb_transaction_id: output.ckb_transaction_id, - contract_id: contract.id, - ) - end - end - end - - puts "done" - end -end diff --git a/test/jobs/import_transaction_job_test.rb b/test/jobs/import_transaction_job_test.rb deleted file mode 100644 index dd535afe2..000000000 --- a/test/jobs/import_transaction_job_test.rb +++ /dev/null @@ -1,138 +0,0 @@ -require "test_helper" - -class ImportTransactionJobTest < ActiveJob::TestCase - # test "the truth" do - # assert true - # end - - # setup the previous cell outputs and contract that the raw tx requires - setup do - end - - test "import normal ckb transaction" do - @cell_base_transaction = create :ckb_transaction, :with_single_output - @cell_base = @cell_base_transaction.cell_outputs.first - @raw_tx = { - "cell_deps" => - [ - { - "dep_type" => "code", - "out_point" => { - "index" => "0x3", - "tx_hash" => "0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f" } }, - { - "dep_type" => "code", - "out_point" => { - "index" => "0x1", - "tx_hash" => "0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f" } } - ], - "hash" => "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37", - "header_deps" => [], - "inputs" => [ - { - "previous_output" => { - "index" => CkbUtils.int_to_hex(@cell_base.cell_index), - "tx_hash" => @cell_base_transaction.tx_hash - }, - "since" => "0x0" - } - ], - "outputs" => - [ - { - "capacity" => CkbUtils.int_to_hex(10**8 * 4), - "lock" => { - "args" => "0x57ccb07be6875f61d93636b0ee11b675494627d2", - "code_hash" => "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", - "hash_type" => "type" - }, - "type" => nil - }, - { - "capacity" => CkbUtils.int_to_hex(10**8 * 4 - 1), - "lock" => { - "args" => "0x64257f00b6b63e987609fa9be2d0c86d351020fb", - "code_hash" => "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", - "hash_type" => "type" - }, - "type" => nil - } - ], - "outputs_data" => [], - "version" => "0x0", - "witnesses" => [ - "0x55f49d7979ba246aa2f05a6e9afd25a23dc39ed9085a0b1e33b6b3bb80d34dbd4031a04ea389d6d8ff5604828889aa06a827e930a7e89411b80f6c3e1404951f00" - ] - } - ImportTransactionJob.new.perform @raw_tx - assert_equal 2, CkbTransaction.count - assert_equal 1, CellInput.count - assert_equal 3, CellOutput.count - assert_equal 4, Address.count - assert_equal 4, AccountBook.count - end - - test "import transaction which wants to consume non-exists cells" do - # this will halt the import process, only leave a pending transaction - raw_tx = { - "cell_deps" => - [ - { - "dep_type" => "code", - "out_point" => { - "index" => "0x3", - "tx_hash" => "0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f" } }, - { - "dep_type" => "code", - "out_point" => { - "index" => "0x1", - "tx_hash" => "0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f" } } - ], - "hash" => "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37", - "header_deps" => [], - "inputs" => [ - { - "previous_output" => { - "index" => "0x0", - "tx_hash" => "0x519c09b28e1170b8ee89523b75965dae2f7dd209e88c98008286e996bad46e07" - }, - "since" => "0x0" - } - ], - "outputs" => - [ - { - "capacity" => CkbUtils.int_to_hex(10**8 * 4), - "lock" => { - "args" => "0x57ccb07be6875f61d93636b0ee11b675494627d2", - "code_hash" => "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", - "hash_type" => "type" - }, - "type" => nil - }, - { - "capacity" => CkbUtils.int_to_hex(10**8 * 4 - 1), - "lock" => { - "args" => "0x64257f00b6b63e987609fa9be2d0c86d351020fb", - "code_hash" => "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", - "hash_type" => "type" - }, - "type" => nil - } - ], - "outputs_data" => [], - "version" => "0x0", - "witnesses" => [ - "0x55f49d7979ba246aa2f05a6e9afd25a23dc39ed9085a0b1e33b6b3bb80d34dbd4031a04ea389d6d8ff5604828889aa06a827e930a7e89411b80f6c3e1404951f00" - ] - } - - assert_difference -> { CkbTransaction.count } => 1, - -> { CellInput.count } => 1, - -> { CellOutput.count } => 2, - -> { AccountBook.count } => 2, - -> { Address.count } => 2 do - ImportTransactionJob.new.perform raw_tx - end - end -end diff --git a/test/models/address_test.rb b/test/models/address_test.rb index 4868723ff..45617d697 100644 --- a/test/models/address_test.rb +++ b/test/models/address_test.rb @@ -11,7 +11,6 @@ class AddressTest < ActiveSupport::TestCase ], ) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) end diff --git a/test/models/block_test.rb b/test/models/block_test.rb index 662a87e13..b09b844fa 100644 --- a/test/models/block_test.rb +++ b/test/models/block_test.rb @@ -6,7 +6,6 @@ class BlockTest < ActiveSupport::TestCase create(:table_record_count, :ckb_transactions_counter) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_block_cycles).returns( [ diff --git a/test/models/cell_output_test.rb b/test/models/cell_output_test.rb index 54f62a353..73b62c66d 100644 --- a/test/models/cell_output_test.rb +++ b/test/models/cell_output_test.rb @@ -6,7 +6,6 @@ class CellOutputTest < ActiveSupport::TestCase should belong_to(:address) # should belong_to(:block) should have_many(:cell_dependencies) - # should have_many(:referring_cells) end context "validations" do @@ -17,14 +16,14 @@ class CellOutputTest < ActiveSupport::TestCase test "should have cell_type column" do block = create(:block) - cell_output = create(:cell_output, :with_full_transaction, block: block) + cell_output = create(:cell_output, :with_full_transaction, block:) assert_equal "normal", cell_output.cell_type end test "#to_raw should contain correct keys" do block = create(:block) - cell_output = create(:cell_output, :with_full_transaction, block: block) + cell_output = create(:cell_output, :with_full_transaction, block:) raw = cell_output.to_raw assert_equal %i(capacity lock type).sort, raw.keys.sort assert_equal raw[:lock][:code_hash], cell_output.lock_script.code_hash diff --git a/test/models/ckb_sync/dao_events_test.rb b/test/models/ckb_sync/dao_events_test.rb index 593d269d7..b4bbd7637 100644 --- a/test/models/ckb_sync/dao_events_test.rb +++ b/test/models/ckb_sync/dao_events_test.rb @@ -16,7 +16,6 @@ class DaoEventsTest < ActiveSupport::TestCase create(:table_record_count, :ckb_transactions_counter) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_block_cycles).returns( [ diff --git a/test/models/ckb_sync/node_data_processor_test.rb b/test/models/ckb_sync/node_data_processor_test.rb index a6d3b34fe..8e3fdf367 100644 --- a/test/models/ckb_sync/node_data_processor_test.rb +++ b/test/models/ckb_sync/node_data_processor_test.rb @@ -20,7 +20,6 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:table_record_count, :ckb_transactions_counter) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) end diff --git a/test/models/ckb_transaction_test.rb b/test/models/ckb_transaction_test.rb index e886069a5..e03f6edd6 100644 --- a/test/models/ckb_transaction_test.rb +++ b/test/models/ckb_transaction_test.rb @@ -15,7 +15,6 @@ class CkbTransactionTest < ActiveSupport::TestCase context "associations" do # should belong_to(:block, required: false) should have_many(:account_books) - should have_many(:referring_cells) should have_many(:addresses).through(:account_books) should have_many(:cell_inputs) should have_many(:cell_outputs) @@ -26,7 +25,6 @@ class CkbTransactionTest < ActiveSupport::TestCase test "#tx_hash should decodes packed string" do GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do CkbSync::Api.any_instance.stubs(:get_epoch_by_number).returns( diff --git a/test/models/deployed_cell_test.rb b/test/models/deployed_cell_test.rb deleted file mode 100644 index 06ba4d5a4..000000000 --- a/test/models/deployed_cell_test.rb +++ /dev/null @@ -1,172 +0,0 @@ -require "test_helper" - -# class DeployedCellTest < ActiveSupport::TestCase -# context "associations" do -# should belong_to(:contract) -# should belong_to(:cell_output) -# end - -# setup do -# @block = create :block, :with_block_hash -# @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block_id: @block.id - -# code_hash = "0x671ddda336db68ce0daebde885f44e2f46406d6c838484b4bd8934173e518876" -# @cell_output = create :cell_output, :with_full_transaction, ckb_transaction_id: @ckb_transaction.id, block: @block, -# data: "0x", data_hash: code_hash -# @contract = create :contract -# @deployed_cell = create :deployed_cell, contract_id: @contract.id, cell_output_id: @cell_output.id -# CellOutput.stubs(:find_by_pointer).returns(@cell_output) -# CellOutput.any_instance.stubs(:data_hash).returns(code_hash) -# CellOutput.any_instance.stubs(:type_hash).returns(code_hash) -# end - -# test "it should create deployed_cell" do -# assert_equal @cell_output.id, @deployed_cell.cell_output_id -# assert_equal @contract.id, @deployed_cell.contract_id -# end - -# test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is type" do -# # step 1 delete redundant data -# delete_redundant_data - -# # step 2 prepare test data -# prepare_test_data_for_hash_type_for_cell_outputs - -# # step 3 start unit test -# # for the 1st time, it will create -# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# @deployed_cell = DeployedCell.first -# contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id -# assert_equal 1, DeployedCell.all.count -# assert_equal contract_id, @deployed_cell.contract_id - -# # for the 2nd time, it should NOT create record -# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# assert_equal 1, DeployedCell.all.count -# end - -# test "it should create_initial_data_for_ckb_transaction for cell_outputs when hash_type is data" do -# # step 1 delete redundant data -# delete_redundant_data -# # step 2 prepare test data -# prepare_test_data_for_hash_type_for_cell_outputs hash_type: "data" -# # step 3 start unit test -# # for the 1st time, it will create -# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# @deployed_cell = DeployedCell.first -# contract_id = @ckb_transaction_with_cell_deps.cell_outputs.first.lock_script.script.contract_id -# assert_equal 1, DeployedCell.all.count -# assert_equal contract_id, @deployed_cell.contract_id - -# # for the 2nd time, it should NOT create record -# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps -# assert_equal 1, DeployedCell.all.count -# end - -# test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is type" do -# # step 1 delete redundant data -# delete_redundant_data - -# # step 2 prepare test data -# prepare_test_data_for_hash_type_for_cell_inputs - -# # step 3 start unit test -# # for the 1st time, it will create -# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps -# @deployed_cell = DeployedCell.first -# contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id -# assert_equal contract_id, @deployed_cell.contract_id -# assert_equal 1, DeployedCell.all.count - -# # for the 2nd time, it should NOT create record -# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# assert_equal 1, DeployedCell.all.count -# end - -# test "it should create_initial_data_for_ckb_transaction for cell_inputs when hash_type is data" do -# # step 1 delete redundant data -# delete_redundant_data -# # step 2 prepare test data -# prepare_test_data_for_hash_type_for_cell_inputs hash_type: "data" -# # step 3 start unit test -# # for the 1st time, it will create -# # DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# @deployed_cell = DeployedCell.first -# contract_id = @ckb_transaction_with_cell_deps.cell_inputs.first.previous_cell_output.lock_script.script.contract_id -# assert_equal contract_id, @deployed_cell.contract_id -# assert_equal 1, DeployedCell.all.count - -# # for the 2nd time, it should NOT create record -# DeployedCell.create_initial_data_for_ckb_transaction @ckb_transaction_with_cell_deps, @cell_deps -# assert_equal 1, DeployedCell.all.count -# end - -# private - -# def delete_redundant_data -# Script.delete_all -# ScriptTransaction.delete_all -# Contract.delete_all -# DeployedCell.delete_all -# CkbTransaction.delete_all -# Block.delete_all -# end - -# def prepare_test_data_for_hash_type_for_cell_outputs(hash_type: "type") -# @contract = create :contract, hash_type: hash_type -# # CKB::Blake2b.hexdigest('0x010200000000008d01f3') -# @deployed_cell = @contract.deployed_cells.first -# code_hash = @contract.code_hash -# tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash -# cell_deps = @cell_deps = [ -# { -# "dep_type" => "code", -# "out_point" => { -# "index" => @deployed_cell.cell_output.cell_index, -# "tx_hash" => tx_hash } } -# ] - -# block = create :block, :with_block_hash -# @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps -# CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all -# script = create :script, contract_id: @contract.id, is_contract: true -# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script: script -# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script: script -# # create test data: cell_outputs -# cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, -# lock_script: lock_script, type_script: type_script -# end - -# def prepare_test_data_for_hash_type_for_cell_inputs(hash_type: "type") -# @contract = create :contract, hash_type: hash_type -# @deployed_cell = @contract.deployed_cells.first -# code_hash = @contract.code_hash -# tx_hash = @deployed_cell.cell_output.ckb_transaction.tx_hash -# cell_deps = @cell_deps = [ -# { -# "dep_type" => "code", -# "out_point" => { -# "index" => @deployed_cell.cell_output.cell_index, -# "tx_hash" => tx_hash } } -# ] - -# block = create :block, :with_block_hash -# @ckb_transaction_with_cell_deps = create :ckb_transaction, block: block, cell_deps: cell_deps -# CkbTransaction.where("id < ?", @ckb_transaction_with_cell_deps.id).delete_all -# script = create :script, contract_id: @contract.id, is_contract: true -# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id -# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id -# # create test data: cell_outputs -# cell_output = create :cell_output, block: block, ckb_transaction: @ckb_transaction_with_cell_deps, -# lock_script: lock_script, type_script: type_script -# temp_ckb_transaction = CkbTransaction.first -# temp_ckb_transaction.update tx_hash: tx_hash -# temp_cell_output = create :cell_output, :with_full_transaction, block: block, ckb_transaction: temp_ckb_transaction -# temp_cell_output.lock_script.update script_id: script.id - -# cell_input = create :cell_input, :with_full_transaction, block: block, -# ckb_transaction: @ckb_transaction_with_cell_deps -# cell_input.update ckb_transaction_id: @ckb_transaction_with_cell_deps.id, previous_cell_output_id: cell_output.id -# cell_input.previous_cell_output.lock_script.update script_id: script.id -# end -# end diff --git a/test/models/lock_script_test.rb b/test/models/lock_script_test.rb index 16c00b889..b7c553630 100644 --- a/test/models/lock_script_test.rb +++ b/test/models/lock_script_test.rb @@ -6,7 +6,6 @@ class LockScriptTest < ActiveSupport::TestCase create(:table_record_count, :ckb_transactions_counter) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_block_cycles).returns( [ diff --git a/test/models/referring_cell_test.rb b/test/models/referring_cell_test.rb deleted file mode 100644 index 09c6aac57..000000000 --- a/test/models/referring_cell_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "test_helper" - -class ReferringCellTest < ActiveSupport::TestCase - context "associations" do - should belong_to(:ckb_transaction) - should belong_to(:contract) - should belong_to(:cell_output) - end - - setup do - @block = create(:block, :with_block_hash) - @ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block_id: @block.id) - @cell_output = create(:cell_output, :with_full_transaction, ckb_transaction_id: @ckb_transaction.id, block: @block) - @contract = create :contract - @referring_cell = create :referring_cell, ckb_transaction_id: @ckb_transaction.id, cell_output_id: @cell_output.id, contract_id: @contract.id - end - - test "it should create referring_cell" do - assert_equal @cell_output.id, @referring_cell.cell_output_id - assert_equal @contract.id, @referring_cell.contract_id - assert_equal @ckb_transaction.id, @referring_cell.ckb_transaction_id - end - - test "it should belongs_to ckb_transaction, cell_output and contract" do - assert_equal @cell_output, @referring_cell.cell_output - assert_equal @contract, @referring_cell.contract - assert_equal @ckb_transaction, @referring_cell.ckb_transaction - end - -end diff --git a/test/models/script_test.rb b/test/models/script_test.rb deleted file mode 100644 index 308d54552..000000000 --- a/test/models/script_test.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "test_helper" - -# class ScriptTest < ActiveSupport::TestCase -# setup do -# @script = create :script -# # create for @cell_dependency -# @block = create :block, :with_block_hash -# @ckb_transaction = create :ckb_transaction, :with_multiple_inputs_and_outputs, block: @block -# @cell_output = create :cell_output, :with_full_transaction, block: @block -# @cell_dependency = create :cell_dependency, ckb_transaction_id: @ckb_transaction.id, contract_cell_id: @cell_output.id, -# script_id: @script.id -# end - -# context "associations" do -# should have_many(:type_scripts) -# should have_many(:cell_dependencies) -# should have_many(:ckb_transactions) -# should have_many(:lock_scripts) -# should have_many(:script_transactions) -# end - -# test "create script" do -# assert_equal false, @script.is_contract -# assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f01855", @script.script_hash -# end - -# test "update script" do -# @script.update is_contract: true, args: "0x441714e000fedf3247292c7f34fb16db14f49d9f1", script_hash: "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551" -# assert_equal true, @script.is_contract -# assert_equal "0x441714e000fedf3247292c7f34fb16db14f49d9f1", @script.args -# assert_equal "0x34551bdd3db215970d4dd031146c4bb5adc74a1faea5c717773c1a72c8f018551", @script.script_hash -# end -# end diff --git a/test/models/script_transaction_test.rb b/test/models/script_transaction_test.rb deleted file mode 100644 index a83aed7b0..000000000 --- a/test/models/script_transaction_test.rb +++ /dev/null @@ -1,61 +0,0 @@ -require "test_helper" - -# class ScriptTransactionTest < ActiveSupport::TestCase -# setup do -# @contract = create :contract -# @block = create(:block, :with_block_hash) -# @script = create :script, contract_id: @contract.id -# @ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: @block) -# @script_transaction = create :script_transaction, script_id: @script.id, ckb_transaction_id: @ckb_transaction.id -# end - -# context "associations" do -# should belong_to(:script) -# should belong_to(:ckb_transaction) -# end - -# test "it should create script_transaction" do -# assert_equal @ckb_transaction.id, @script_transaction.ckb_transaction_id -# assert_equal @script.id, @script_transaction.script_id -# end - -# test "it should update script_transaction" do -# @script_transaction.update ckb_transaction_id: @ckb_transaction.id - 1, script_id: @script.id - 1 -# assert_equal @ckb_transaction.id - 1, @script_transaction.ckb_transaction_id -# assert_equal @script.id - 1, @script_transaction.script_id -# end - -# test "it should create_initial_data" do -# TypeScript.delete_all -# LockScript.delete_all -# Script.delete_all -# ScriptTransaction.delete_all -# Block.delete_all -# Contract.delete_all -# CellOutput.delete_all - -# hash_type = 'type' -# code_hash = "0x1c04df09d9adede5bfc40ff1a39a3a17fc8e29f15c56f16b7e48680c600ee5ac" -# contract = create :contract, code_hash: code_hash, hash_type: hash_type -# block = create :block, :with_block_hash -# ckb_transaction = create(:ckb_transaction, :with_multiple_inputs_and_outputs, block: block) -# CkbTransaction.where('id > ?', ckb_transaction.id).delete_all -# script = create :script -# type_script = create :type_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id -# lock_script = create :lock_script, code_hash: code_hash, hash_type: hash_type, script_id: script.id -# cell_output = create :cell_output, :with_full_transaction, block_id: block.id -# cell_output.update lock_script_id: lock_script.id, type_script_id: type_script.id, ckb_transaction_id: ckb_transaction.id - -# # for the 1st time, it will create -# ScriptTransaction.create_initial_data -# @script_transaction = ScriptTransaction.first -# assert_equal 1, ScriptTransaction.all.count -# assert_equal ckb_transaction.id, @script_transaction.ckb_transaction_id -# assert_equal script.id, @script_transaction.script_id - -# # for the 2nd time, it should NOT create new record -# ScriptTransaction.create_initial_data -# assert_equal 1, ScriptTransaction.all.count -# end - -# end diff --git a/test/models/type_script_test.rb b/test/models/type_script_test.rb index 1bb609e89..63e8e48a5 100644 --- a/test/models/type_script_test.rb +++ b/test/models/type_script_test.rb @@ -17,7 +17,6 @@ class TypeScriptTest < ActiveSupport::TestCase test "#code_hash should decodes packed string" do GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_epoch_by_number).returns( CKB::Types::Epoch.new( diff --git a/test/models/uncle_block_test.rb b/test/models/uncle_block_test.rb index c0c5fd9e1..28f21343d 100644 --- a/test/models/uncle_block_test.rb +++ b/test/models/uncle_block_test.rb @@ -6,7 +6,6 @@ class UncleBlockTest < ActiveSupport::TestCase create(:table_record_count, :ckb_transactions_counter) CkbSync::Api.any_instance.stubs(:get_blockchain_info).returns(OpenStruct.new(chain: "ckb_testnet")) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_block_cycles).returns( [ diff --git a/test/test_helper.rb b/test/test_helper.rb index c220d04c2..3c9406b8c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -48,7 +48,6 @@ def prepare_node_data(node_tip_block_number = 30) Sidekiq::Testing.inline! GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(node_tip_block_number + 1) CkbSync::Api.any_instance.stubs(:get_epoch_by_number).returns( diff --git a/test/utils/ckb_utils_test.rb b/test/utils/ckb_utils_test.rb index e492954d8..c2e7a60db 100644 --- a/test/utils/ckb_utils_test.rb +++ b/test/utils/ckb_utils_test.rb @@ -19,7 +19,6 @@ class CkbUtilsTest < ActiveSupport::TestCase ], ) GenerateStatisticsDataWorker.any_instance.stubs(:perform).returns(true) - GenerateCellDependenciesWorker.any_instance.stubs(:perform).returns(true) BitcoinTransactionDetectWorker.any_instance.stubs(:perform).returns(true) end From a6c7f8605df6b8c0eb052e65b48961c0903a4685 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Fri, 6 Dec 2024 12:46:02 +0900 Subject: [PATCH 10/11] feat: use task to analyze contract from start block (#2319) Signed-off-by: Miles Zhang --- .../analyze_contract_from_start_block.rake | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 lib/tasks/migration/analyze_contract_from_start_block.rake diff --git a/lib/tasks/migration/analyze_contract_from_start_block.rake b/lib/tasks/migration/analyze_contract_from_start_block.rake new file mode 100644 index 000000000..d97c4e78f --- /dev/null +++ b/lib/tasks/migration/analyze_contract_from_start_block.rake @@ -0,0 +1,194 @@ +namespace :migration do + desc "Usage: RAILS_ENV=production bundle exec rake migration:analyze_contract_from_start_block" + task analyze_contract_from_start_block: :environment do + loop do + cell_deps_out_points_attrs = Set.new + contract_attrs = Set.new + cell_deps_attrs = Set.new + + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).limit(1000).each do |cell_dep| + cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } + + next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? + + ckb_transaction = CkbTransaction.find(cell_dep.ckb_transaction_id) + + type_script_hashes = Set.new + lock_script_hashes = Set.new + + cell_outputs = ckb_transaction.cell_outputs.includes(:type_script, :lock_script).to_a + cell_inputs = ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output) + cell_inputs.each do |input| + lock_script_hashes << input.lock_script.code_hash + type_script_hashes << input.type_script.code_hash if input.type_script + end + + cell_outputs.each do |output| + lock_script_hashes << output.lock_script.code_hash + type_script_hashes << output.type_script.code_hash if output.type_script + end + + case cell_dep.dep_type + when "code" + cell_output = cell_dep.cell_output + cell_deps_out_points_attrs << { + tx_hash: cell_output.tx_hash, + cell_index: cell_output.cell_index, + deployed_cell_output_id: cell_output.id, + contract_cell_id: cell_output.id, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + 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:, + is_lock_script:, + deployed_args: cell_output.type_script&.args, + } + end + + 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 = cell_dep.cell_output + + binary_data = mid_cell.binary_data + # 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| + part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<") + + tx_hash = "0x#{part_tx_hash}" + 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, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + contract_attrs << + { + type_hash: cell_output.type_script&.script_hash, + data_hash: cell_output.data_hash, + deployed_cell_output_id: cell_output.id, + deployed_args: cell_output.type_script&.args, + is_type_script:, + is_lock_script:, + } + end + end + end + cell_deps_out_points_attrs = Set.new + contract_attrs = Set.new + cell_deps_attrs = Set.new + + CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(1000).each do |cell_dep| + cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } + + next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? + + ckb_transaction = CkbTransaction.find(cell_dep.ckb_transaction_id) + + type_script_hashes = Set.new + lock_script_hashes = Set.new + + cell_outputs = ckb_transaction.cell_outputs.includes(:type_script, :lock_script).to_a + cell_inputs = ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output) + cell_inputs.each do |input| + lock_script_hashes << input.lock_script.code_hash + type_script_hashes << input.type_script.code_hash if input.type_script + end + + cell_outputs.each do |output| + lock_script_hashes << output.lock_script.code_hash + type_script_hashes << output.type_script.code_hash if output.type_script + end + + case cell_dep.dep_type + when "code" + cell_output = cell_dep.cell_output + cell_deps_out_points_attrs << { + tx_hash: cell_output.tx_hash, + cell_index: cell_output.cell_index, + deployed_cell_output_id: cell_output.id, + contract_cell_id: cell_output.id, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + 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:, + is_lock_script:, + deployed_args: cell_output.type_script&.args, + } + end + + 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 = cell_dep.cell_output + + binary_data = mid_cell.binary_data + # 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| + part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<") + + tx_hash = "0x#{part_tx_hash}" + 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, + } + + is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) + is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) + + if is_lock_script || is_type_script + contract_attrs << + { + type_hash: cell_output.type_script&.script_hash, + data_hash: cell_output.data_hash, + deployed_cell_output_id: cell_output.id, + deployed_args: cell_output.type_script&.args, + is_type_script:, + is_lock_script:, + } + end + end + end + end + end + if cell_deps_out_points_attrs.any? + CellDepsOutPoint.upsert_all(cell_deps_out_points_attrs, + unique_by: %i[contract_cell_id deployed_cell_output_id]) + end + Contract.upsert_all(contract_attrs, unique_by: %i[deployed_cell_output_id]) if contract_attrs.any? + CellDependency.upsert_all(cell_deps_attrs, unique_by: %i[ckb_transaction_id contract_cell_id dep_type], update_only: :contract_analyzed) + + puts cell_deps_attrs.to_a.last[:ckb_transaction_id] + + break unless CellDependency.where(contract_analyzed: false).where.not(block_number: nil).exists? + end + puts "DONE" + end +end From aaf9f3d81779357133c9310ec44727105c560dff Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Fri, 6 Dec 2024 14:38:37 +0900 Subject: [PATCH 11/11] fix: analyze_contract task (#2321) Signed-off-by: Miles Zhang --- .../analyze_contract_from_start_block.rake | 89 +------------------ 1 file changed, 1 insertion(+), 88 deletions(-) diff --git a/lib/tasks/migration/analyze_contract_from_start_block.rake b/lib/tasks/migration/analyze_contract_from_start_block.rake index d97c4e78f..87fde67a8 100644 --- a/lib/tasks/migration/analyze_contract_from_start_block.rake +++ b/lib/tasks/migration/analyze_contract_from_start_block.rake @@ -89,95 +89,8 @@ namespace :migration do end end end - cell_deps_out_points_attrs = Set.new - contract_attrs = Set.new - cell_deps_attrs = Set.new - - CellDependency.where(contract_analyzed: false).where.not(block_number: nil).order("block_number desc").limit(1000).each do |cell_dep| - cell_deps_attrs << { contract_analyzed: true, ckb_transaction_id: cell_dep.ckb_transaction_id, contract_cell_id: cell_dep.contract_cell_id, dep_type: cell_dep.dep_type } - - next if CellDepsOutPoint.where(contract_cell_id: cell_dep.contract_cell_id).exists? - - ckb_transaction = CkbTransaction.find(cell_dep.ckb_transaction_id) - - type_script_hashes = Set.new - lock_script_hashes = Set.new - - cell_outputs = ckb_transaction.cell_outputs.includes(:type_script, :lock_script).to_a - cell_inputs = ckb_transaction.cell_inputs.includes(:previous_cell_output).map(&:previous_cell_output) - cell_inputs.each do |input| - lock_script_hashes << input.lock_script.code_hash - type_script_hashes << input.type_script.code_hash if input.type_script - end - - cell_outputs.each do |output| - lock_script_hashes << output.lock_script.code_hash - type_script_hashes << output.type_script.code_hash if output.type_script - end - - case cell_dep.dep_type - when "code" - cell_output = cell_dep.cell_output - cell_deps_out_points_attrs << { - tx_hash: cell_output.tx_hash, - cell_index: cell_output.cell_index, - deployed_cell_output_id: cell_output.id, - contract_cell_id: cell_output.id, - } - - is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) - is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) - - if is_lock_script || is_type_script - 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:, - is_lock_script:, - deployed_args: cell_output.type_script&.args, - } - end - - 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 = cell_dep.cell_output - - binary_data = mid_cell.binary_data - # 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| - part_tx_hash, cell_index = binary_data[4 + i * 36, 36].unpack("H64L<") - - tx_hash = "0x#{part_tx_hash}" - 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, - } - - is_lock_script = cell_output.type_script&.script_hash.in?(lock_script_hashes) || cell_output.data_hash.in?(lock_script_hashes) - is_type_script = cell_output.type_script&.script_hash.in?(type_script_hashes) || cell_output.data_hash.in?(type_script_hashes) - - if is_lock_script || is_type_script - contract_attrs << - { - type_hash: cell_output.type_script&.script_hash, - data_hash: cell_output.data_hash, - deployed_cell_output_id: cell_output.id, - deployed_args: cell_output.type_script&.args, - is_type_script:, - is_lock_script:, - } - end - end - end - end end + if cell_deps_out_points_attrs.any? CellDepsOutPoint.upsert_all(cell_deps_out_points_attrs, unique_by: %i[contract_cell_id deployed_cell_output_id])