Skip to content

Commit

Permalink
Merge pull request #1623 from nervosnetwork/develop
Browse files Browse the repository at this point in the history
Deploy to testnet
  • Loading branch information
rabbitz authored Feb 20, 2024
2 parents cb3ee9d + 0f9ef08 commit e3cc632
Show file tree
Hide file tree
Showing 21 changed files with 318 additions and 222 deletions.
94 changes: 64 additions & 30 deletions app/controllers/concerns/cell_data_comparator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ def compare_cells(transaction)
udt_transfers = diff_udt_cells(inputs, outputs)
cota_nft_transfers = diff_cota_nft_cells(transaction, inputs, outputs)
normal_nft_transfers = diff_normal_nft_cells(inputs, outputs)
nft_class_transfers = diff_nft_capacities(inputs, outputs)
dao_transfers = diff_dao_capacities(inputs, outputs)

merged_transfers =
[normal_transfers, udt_transfers, cota_nft_transfers, normal_nft_transfers, nft_class_transfers].reduce do |acc, h|
[normal_transfers, udt_transfers, cota_nft_transfers, normal_nft_transfers, dao_transfers].reduce do |acc, h|
acc.merge(h) { |_, ov, nv| ov + nv }
end

Expand Down Expand Up @@ -73,6 +73,20 @@ def diff_udt_cells(inputs, outputs)
transfers
end

def diff_dao_capacities(inputs, outputs)
transfers = Hash.new { |h, k| h[k] = Array.new }
cell_types = %w(nervos_dao_deposit nervos_dao_withdrawing)
inputs = inputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity)
outputs = outputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity)

(inputs.keys | outputs.keys).each do |k|
capacity = outputs[k].to_f - inputs[k].to_f
transfers[k[0]] << CkbUtils.hash_value_to_s({ capacity:, cell_type: k[1] })
end

transfers
end

def diff_cota_nft_cells(transaction, inputs, outputs)
transfers = Hash.new { |h, k| h[k] = Array.new }
inputs = inputs.cota_regular.group(:address_id).sum(:capacity)
Expand All @@ -88,58 +102,78 @@ def diff_cota_nft_cells(transaction, inputs, outputs)

def diff_normal_nft_cells(inputs, outputs)
transfers = Hash.new { |h, k| h[k] = Array.new }
cell_types = %w(m_nft_token nrc_721_token spore_cell)
nft_infos = Hash.new { |h, k| h[k] = nil }
cell_types = %w(m_nft_token nrc_721_token spore_cell m_nft_issuer m_nft_class nrc_721_factory cota_registry spore_cluster)

process_nft = ->(c, h) {
process_nft = ->(c, h, o) {
k = [c.address_id, c.cell_type, c.type_hash]
h[k] ||= { capacity: 0.0, count: 0 }
h[k][:capacity] += c.capacity
h[k][:count] -= 1
h[k][:count] += o

unless nft_infos[c.type_hash]
nft_infos[c.type_hash] = nft_info(c)
end
}
inputs = inputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h) }
outputs = outputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h) }
inputs = inputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h, -1) }
outputs = outputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h, 1) }

(inputs.keys | outputs.keys).each do |k|
address_id, cell_type, type_hash = k
token_id, collection_name = token_info(type_hash)
input = inputs[k]
output = outputs[k]
capacity = output&.dig(:capacity).to_f - input&.dig(:capacity).to_f
count = output&.dig(:count).to_i + input&.dig(:count).to_i
transfers[address_id] << CkbUtils.hash_value_to_s({ capacity:, cell_type:, token_id:, collection_name:, count: })
transfer = { capacity:, cell_type:, count: }
transfer.merge!(nft_infos[type_hash]) if nft_infos[type_hash]
transfers[address_id] << CkbUtils.hash_value_to_s(transfer)
end

transfers
end

def diff_nft_capacities(inputs, outputs)
transfers = Hash.new { |h, k| h[k] = Array.new }
cell_types = %w(m_nft_issuer m_nft_class nrc_721_factory cota_registry spore_cluster)
inputs = inputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity)
outputs = outputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity)

(inputs.keys | outputs.keys).each do |k|
capacity = outputs[k].to_f - inputs[k].to_f
transfers[k[0]] << CkbUtils.hash_value_to_s({ capacity:, cell_type: k[1] })
def nft_info(cell)
case cell.cell_type
when "m_nft_token", "nrc_721_token", "spore_cell"
item = TokenItem.joins(:type_script).where(type_script: { script_hash: cell.type_hash }).take
{ toekn_id: item&.token_id, name: item&.collection&.name }
when "m_nft_issuer"
{ name: CkbUtils.parse_issuer_data(cell.data).info["name"] }
when "m_nft_class"
{ name: CkbUtils.parse_token_class_data(cell.data).name }
when "nrc_721_factory"
type_script = cell.type_script
factory_cell = NrcFactoryCell.find_by(
code_hash: type_script.code_hash,
hash_type: type_script.hash_type,
args: type_script.args,
verified: true,
)
{ name: factory_cell&.name }
when "spore_cluster"
{ name: CkbUtils.parse_spore_cluster_data(cell.data)[:name] }
when "omiga_inscription_info"
type_script = cell.type_script
info = OmigaInscriptionInfo.find_by(
code_hash: type_script.code_hash,
hash_type: type_script.hash_type,
args: type_script.args,
)
{ name: info&.name }
end

transfers
end

def token_info(script_hash)
item = TokenItem.joins(:type_script).where(type_script: { script_hash: }).take
[item&.token_id, item&.collection&.name]
end

def cota_info(transaction, address_id)
info = Array.new
process_transfer = ->(item, count) {
collection = item.collection
info << CkbUtils.hash_value_to_s({
collection_name: collection.name,
count:,
token_id: item.token_id,
})
info << CkbUtils.hash_value_to_s(
{
name: collection.name,
count:,
token_id: item.token_id,
},
)
}

transaction.token_transfers.each do |t|
Expand Down
76 changes: 39 additions & 37 deletions app/jobs/import_transaction_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ def perform(tx_hash, extra_data = {})
CkbTransaction.write_raw_hash_cache tx_hash["hash"], tx_hash
tx_hash = tx_hash["hash"]
end
# raw = CkbTransaction.fetch_raw_hash(tx_hash)
@tx = CkbTransaction.unscoped.create_with(tx_status: :pending).find_or_create_by! tx_hash: tx_hash
@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}"
Expand Down Expand Up @@ -49,23 +48,23 @@ def perform(tx_hash, extra_data = {})
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: index
index:,
).create_or_find_by(
previous_cell_output_id: nil,
from_cell_base: true
from_cell_base: true,
)
else
cell = CellOutput.find_by(
tx_hash: input.previous_output.tx_hash,
cell_index: input.previous_output.index
cell_index: input.previous_output.index,
)

if cell
process_input tx.cell_inputs.create_with(
previous_cell_output_id: cell.id
previous_cell_output_id: cell.id,
).create_or_find_by!(
ckb_transaction_id: txid,
index: index
index:,
)
process_deployed_cell(cell.lock_script)
process_deployed_cell(cell.type_script) if cell.type_script
Expand All @@ -74,7 +73,8 @@ def perform(tx_hash, extra_data = {})
tx.cell_inputs.create_or_find_by!(
previous_tx_hash: input.previous_output.tx_hash,
previous_index: input.previous_output.index,
since: input.since
since: input.since,
index:,
)
puts "Missing input #{input.previous_output.to_h} in #{tx_hash}"
# cannot find corresponding cell output,
Expand All @@ -93,22 +93,24 @@ def perform(tx_hash, extra_data = {})
lock = LockScript.process(output.lock)
t = TypeScript.process(output.type) if output.type
cell = tx.cell_outputs.find_or_create_by(
tx_hash: tx_hash,
cell_index: index
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"
status: "pending",
)
puts "output cell created tx_hash: #{tx_hash}, index: #{index}, cell_id: #{cell.id}"
# 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

process_output cell
process_deployed_cell(cell.lock_script)
Expand Down Expand Up @@ -139,7 +141,7 @@ def parse_code_dep(cell_dep)
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
implicit: cell_dep["implicit"] || false,
}

# we don't know how the cells in transaction may refer to the contract cell
Expand All @@ -165,13 +167,13 @@ def save_relationship
if cell_dependencies_attrs.present?
CellDependency.upsert_all cell_dependencies_attrs.uniq { |a|
a[:contract_cell_id]
}, unique_by: [:ckb_transaction_id, :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]
deployed_cell_attr[:contract_id],
)
end
end
Expand All @@ -184,10 +186,10 @@ def process_deployed_cell(lock_script_or_type_script)

dep =
case lock_script_or_type_script.hash_type
when "data"
by_data_hash[lock_script_or_type_script.code_hash]
when "type"
by_type_hash[lock_script_or_type_script.code_hash]
when "data"
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

Expand All @@ -204,7 +206,7 @@ def process_deployed_cell(lock_script_or_type_script)

deployed_cells_attrs << {
contract_id: contract.id,
cell_output_id: dep[:contract_cell_id]
cell_output_id: dep[:contract_cell_id],
}
end
end
Expand All @@ -229,7 +231,7 @@ def process_cell_dep(cell_dep)
dep_type: cell_dep["dep_type"],
ckb_transaction_id: ckb_transaction.id,
contract_id: nil,
implicit: false
implicit: false,
}
binary_data = mid_cell.binary_data
# binary_data = [hex_data[2..-1]].pack("H*")
Expand All @@ -244,10 +246,10 @@ def process_cell_dep(cell_dep)
parse_code_dep(
"out_point" => {
"tx_hash" => "0x#{tx_hash}",
"index" => cell_index
"index" => cell_index,
},
"dep_type" => "code",
"implicit" => true # this is an implicit dependency
"implicit" => true, # this is an implicit dependency
)
end
end
Expand All @@ -258,8 +260,8 @@ def process_header_deps
sdk_tx.header_deps.each_with_index do |header_dep, index|
header_deps_attrs << {
ckb_transaction_id: txid,
index: index,
header_hash: header_dep
index:,
header_hash: header_dep,
}
end
if header_deps_attrs.present?
Expand All @@ -274,7 +276,7 @@ def process_witnesses
witnesses_attrs << {
ckb_transaction_id: txid,
index: i,
data: w
data: w,
}
end
if witnesses_attrs.present?
Expand All @@ -291,7 +293,7 @@ def process_input(cell_input)
changes = address_changes[address_id] ||=
{
balance: 0,
balance_occupied: 0
balance_occupied: 0,
}
changes[:balance] -= cell_output.capacity
changes[:balance_occupied] -= cell_output.occupied_capacity if cell_output.occupied_capacity
Expand All @@ -304,7 +306,7 @@ def process_output(cell_output)
changes = address_changes[address_id] ||=
{
balance: 0,
balance_occupied: 0
balance_occupied: 0,
}
changes[:balance] += cell_output.capacity
changes[:balance_occupied] += cell_output.occupied_capacity
Expand All @@ -315,19 +317,19 @@ def save_changes
attrs =
address_changes.map do |address_id, c|
{
address_id: address_id,
address_id:,
ckb_transaction_id: txid,
changes: c
changes: c,
}
end
TransactionAddressChange.upsert_all(
attrs,
unique_by: [:address_id, :ckb_transaction_id],
unique_by: %i[address_id ckb_transaction_id],
on_duplicate: Arel.sql(
"changes = transaction_address_changes.changes || excluded.changes"
)
"changes = transaction_address_changes.changes || excluded.changes",
),
)
AccountBook.upsert_all address_changes.keys.map{|address_id| {ckb_transaction_id: tx.id, address_id:}}
AccountBook.upsert_all address_changes.keys.map { |address_id| { ckb_transaction_id: tx.id, address_id: } }
end
end
end
2 changes: 1 addition & 1 deletion app/models/cell_output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ def nrc_721_nft_info
type_hash:,
published: factory_cell&.verified,
display_name: factory_cell&.name,
nan: "",
uan: "",
}
when "nrc_721_token"
udt = Udt.find_by(type_hash:)
Expand Down
Loading

0 comments on commit e3cc632

Please sign in to comment.