Skip to content

Commit

Permalink
fix: add a guard in send_capacity to check whether the capacity is …
Browse files Browse the repository at this point in the history
…enough to hold the output

Also fix `calculate_bytesize` in `Script`
  • Loading branch information
classicalliu committed May 25, 2019
1 parent 616c8bc commit 8fc7dae
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 48 deletions.
7 changes: 5 additions & 2 deletions lib/ckb/types/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
module CKB
module Types
class Output
attr_reader :data, :lock, :type, :out_point
attr_accessor :capacity
attr_reader :data, :lock, :type, :out_point, :capacity

# @param capacity [String]
# @param data: [String] 0x...
Expand All @@ -19,6 +18,10 @@ def initialize(capacity:, data: "0x", lock:, type: nil, out_point: nil)
@out_point = out_point
end

def capacity=(value)
@capacity = value.to_s
end

def calculate_bytesize
bytesize = 8 + Utils.hex_to_bin(@data).bytesize + @lock.calculate_bytesize
bytesize += @type.calculate_bytesize if @type
Expand Down
7 changes: 4 additions & 3 deletions lib/ckb/types/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ def initialize(code_hash:, args:)
@args = args
end

# @return [Integer]
# @return [Integer] Byte
def calculate_bytesize
bytesize = (@args || []).map(&:bytesize).reduce(0, &:+)
bytesize += Utils.hex_to_bin(@code_hash).bytesize if @code_hash
bytesize = 0
bytesize = Utils.hex_to_bin(@code_hash).bytesize if @code_hash
(@args || []).map { |arg| Utils.hex_to_bin(arg).bytesize }.reduce(bytesize, &:+)
end

def to_h
Expand Down
78 changes: 43 additions & 35 deletions lib/ckb/wallet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
require "secp256k1"

module CKB
MIN_CELL_CAPACITY = 40 * (10**8)

DAO_CODE_HASH = "0x0000000000000000000000000000004e4552564f5344414f434f444530303031"

DAO_ISSUING_OUT_POINT = Types::OutPoint.new(
Expand Down Expand Up @@ -50,25 +48,30 @@ def get_balance
end

def generate_tx(target_address, capacity, data = "0x")
i = gather_inputs(capacity, MIN_CELL_CAPACITY)
output = Types::Output.new(
capacity: capacity,
data: data,
lock: Types::Script.generate_lock(
key.address.parse(target_address),
api.system_script_code_hash
)
)

charge_output = Types::Output.new(
capacity: 0,
lock: lock
)

i = gather_inputs(
capacity,
output.calculate_min_capacity,
charge_output.calculate_min_capacity
)
input_capacities = i.capacities

outputs = [
Types::Output.new(
capacity: capacity,
data: data,
lock: Types::Script.generate_lock(
key.address.parse(target_address),
api.system_script_code_hash
)
)
]
if input_capacities > capacity
outputs << Types::Output.new(
capacity: input_capacities - capacity,
lock: lock
)
end
outputs = [output]
charge_output.capacity = input_capacities - capacity
outputs << charge_output if charge_output.capacity.to_i > 0

tx = Types::Transaction.new(
version: 0,
Expand All @@ -90,21 +93,26 @@ def send_capacity(target_address, capacity, data = "0x")
end

def deposit_to_dao(capacity)
i = gather_inputs(capacity, MIN_CELL_CAPACITY)
output = Types::Output.new(
capacity: capacity,
lock: Types::Script.generate_lock(@key.address.blake160, DAO_CODE_HASH)
)

charge_output = Types::Output.new(
capacity: 0,
lock: lock
)

i = gather_inputs(
capacity,
output.calculate_min_capacity,
charge_output.calculate_min_capacity
)
input_capacities = i.capacities

outputs = [
Types::Output.new(
capacity: capacity,
lock: Types::Script.generate_lock(@key.address.blake160, DAO_CODE_HASH)
)
]
if input_capacities > capacity
outputs << Types::Output.new(
capacity: input_capacities - capacity,
lock: lock
)
end
outputs = [output]
charge_output.capacity = input_capacities - capacity
outputs << charge_output if charge_output.capacity.to_i > 0

tx = Types::Transaction.new(
version: 0,
Expand Down Expand Up @@ -189,7 +197,7 @@ def send_transaction(transaction)

# @param capacity [Integer]
# @param min_capacity [Integer]
def gather_inputs(capacity, min_capacity)
def gather_inputs(capacity, min_capacity, min_charge_capacity)
raise "capacity cannot be less than #{min_capacity}" if capacity < min_capacity

input_capacities = 0
Expand All @@ -206,10 +214,10 @@ def gather_inputs(capacity, min_capacity)
input_capacities += cell.capacity.to_i

diff = input_capacities - capacity
break if input_capacities >= capacity && (diff >= min_capacity || diff.zero?)
break if diff >= 0 && (diff >= min_charge_capacity || diff.zero?)
end

raise "Not enough capacity!" if input_capacities < capacity
raise "Capacity not enough!" if input_capacities < capacity

OpenStruct.new(inputs: inputs, capacities: input_capacities, pubkeys: pubkeys)
end
Expand Down
41 changes: 33 additions & 8 deletions spec/ckb/types/output_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,43 @@
let(:output) do
CKB::Types::Output.new(
capacity: "4500000000",
data: "0x72796c6169",
lock: CKB::Types::Script.new(
args: [],
code_hash: "0xb35557e7e9854206f7bc13e3c3a7fa4cf8892c84a09237fb0aab40aab3771eee",
),
type: nil
args: ["0x36c329ed630d6ce750712a477543672adab57f4c"],
code_hash: "0x9e3b3557f11b2b3532ce352bfe8017e9fd11d154c4c7f9b7aaaa1e621b539a08",
)
)
end

it "bytesize" do
context "calculate bytesize" do
it "default" do
expect(
output.calculate_bytesize
).to eq 60
end

it "with data" do
output.instance_variable_set(:@data, "0x1234")
expect(
output.calculate_bytesize
).to eq 62
end

it "with type script" do
type_script = CKB::Types::Script.new(
args: [],
code_hash: "0x9e3b3557f11b2b3532ce352bfe8017e9fd11d154c4c7f9b7aaaa1e621b539a08",
)
output.instance_variable_set(:@type, type_script)

expect(
output.calculate_bytesize
).to eq 92
end
end

it "calculate min capacity" do
expect(
output.calculate_bytesize
).to eq 45
output.calculate_min_capacity
).to eq CKB::Utils.byte_to_shannon(60)
end
end
19 changes: 19 additions & 0 deletions spec/ckb/types/script_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@
script.to_hash
).to eq code_hash
end

context "calculate bytesize" do
let(:code_hash) { "0x9e3b3557f11b2b3532ce352bfe8017e9fd11d154c4c7f9b7aaaa1e621b539a08" }
let(:args) { ["0x36c329ed630d6ce750712a477543672adab57f4c"] }

let(:lock_script) do
CKB::Types::Script.new(
code_hash: code_hash,
args: args
)
end
let(:min_capacity) { 52 }

it "success" do
expect(
lock_script.calculate_bytesize
).to eq (min_capacity)
end
end
end

0 comments on commit 8fc7dae

Please sign in to comment.