Skip to content

Commit

Permalink
Merge pull request #175 from nervosnetwork/rc/v0.21.0
Browse files Browse the repository at this point in the history
[ᚬmaster] Rc/v0.21.0
  • Loading branch information
classicalliu authored Sep 21, 2019
2 parents 19e04b7 + 87ef418 commit d3a4488
Show file tree
Hide file tree
Showing 63 changed files with 1,404 additions and 424 deletions.
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [v0.21.0](https://github.com/nervosnetwork/ckb-sdk-ruby/compare/v0.20.0...v0.21.0) (2019-09-21)


### Bug Fixes

* return hex string format type ([c3c9af7](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/c3c9af7))


### Features

* add cell data ([4e7d661](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/4e7d661))
* add cell info ([8b47dcb](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/8b47dcb))
* add chain_root to block header ([af3f10f](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/af3f10f))
* add errors on Address ([66dc62a](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/66dc62a))
* add to_raw_transaction_h method ([9e14366](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/9e14366))
* add with_data to get_live_cell ([40e85d3](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/40e85d3))
* add with_hash to transaction to_h ([55abb63](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/55abb63))
* change all number to integer and convert to hex string in RPC interface ([a1f0495](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/a1f0495))
* change to class method ([4a7ea7e](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/4a7ea7e))
* implement new type addresses ([d2b7a98](https://github.com/nervosnetwork/ckb-sdk-ruby/commit/d2b7a98))


### BREAKING CHANGES

* All number type changed to integer and will convert to hex string in RPC interface


# [v0.20.0](https://github.com/nervosnetwork/ckb-sdk-ruby/compare/v0.19.0...v0.20.0) (2019-09-07)


Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
ckb-sdk-ruby (0.20.0)
ckb-sdk-ruby (0.21.0)
bitcoin-secp256k1 (~> 0.5.2)
net-http-persistent (~> 3.0.0)
rbnacl (~> 6.0, >= 6.0.1)
Expand Down
2 changes: 1 addition & 1 deletion lib/bech32.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def decode(bech)
bech = bech.downcase
# check data length
pos = bech.rindex(SEPARATOR)
return nil if pos.nil? || pos < 1 || pos + 7 > bech.length || bech.length > 90
return nil if pos.nil? || pos < 1 || pos + 7 > bech.length
# check valid charset
bech[pos+1..-1].each_char{|c|return nil unless CHARSET.include?(c)}
# split hrp and data
Expand Down
111 changes: 102 additions & 9 deletions lib/ckb/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class Address

DEFAULT_MODE = MODE::TESTNET

TYPE = "01"
CODE_HASH_INDEX = "00"
TYPES = %w(01 02 04)
CODE_HASH_INDEXES = %w(00 01)

def initialize(blake160, mode: DEFAULT_MODE)
@mode = mode
Expand All @@ -21,39 +21,126 @@ def initialize(blake160, mode: DEFAULT_MODE)

# Generates address assuming default lock script is used
# payload = type(01) | code hash index(00) | pubkey blake160
# see https://github.com/nervosnetwork/ckb/wiki/Common-Address-Format for more info.
# see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md for more info.
def generate
blake160_bin = [blake160[2..-1]].pack("H*")
type = [TYPE].pack("H*")
code_hash_index = [CODE_HASH_INDEX].pack("H*")
type = [TYPES[0]].pack("H*")
code_hash_index = [CODE_HASH_INDEXES[0]].pack("H*")
payload = type + code_hash_index + blake160_bin
ConvertAddress.encode(@prefix, payload)
end

# Generates short payload format address
# payload = type(01) | code hash index(01) | pubkey hash160
# see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md for more info.
# @param [String] hash160
# @return [String]
def self.generate_short_payload_hash160_address(hash160, mode: DEFAULT_MODE)
prefix = prefix(mode: mode)
hash160_bin = [hash160[2..-1]].pack("H*")
type = [TYPES[0]].pack("H*")
code_hash_index = [CODE_HASH_INDEXES[1]].pack("H*")
payload = type + code_hash_index + hash160_bin
ConvertAddress.encode(prefix, payload)
end

# Generates full payload format address
# payload = 0x02/0x04 | code_hash | len(arg[0]) | arg[0] | ...
# see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0021-ckb-address-format/0021-ckb-address-format.md for more info.
# @param [String | Integer] format_type
# @param [String] code_hash
# @param [String[]] args
# @return [String]
def self.generate_full_payload_address(format_type, code_hash, args, mode: DEFAULT_MODE)
prefix = prefix(mode: mode)
format_type = Utils.to_hex(format_type)[2..-1].rjust(2, '0')
raise InvalidFormatTypeError.new("Invalid format type") unless TYPES[1..-1].include?(format_type)
raise InvalidArgsTypeError.new("Args should be an array") unless args.is_a?(Array)

payload = [format_type].pack("H*") + CKB::Utils.hex_to_bin(code_hash)
args.each do |arg|
arg_bytes = CKB::Utils.hex_to_bin(arg)
arg_len = arg_bytes.bytesize
if arg_len > 256
raise InvalidArgSizeError.new("The maximum size of arg is 256")
else
payload += [arg_len].pack("C") + arg_bytes
end
end

CKB::ConvertAddress.encode(prefix, payload)
end

alias to_s generate

# Parse address into lock assuming default lock script is used
def parse(address)
self.class.parse(address, mode: @mode)
end

def self.parse(address, mode: DEFAULT_MODE)
def self.parse_short_payload_address(address, mode: DEFAULT_MODE)
decoded_prefix, data = ConvertAddress.decode(address)
format_type = data[0].unpack("H*").first
code_hash_index = data[1].unpack("H*").first

raise "Invalid prefix" if decoded_prefix != prefix(mode: mode)

raise "Invalid type/code hash index" if data.slice(0..1) != [TYPE + CODE_HASH_INDEX].pack("H*")
raise InvalidPrefixError.new("Invalid prefix") if decoded_prefix != prefix(mode: mode)
raise InvalidFormatTypeError.new("Invalid format type") if format_type != TYPES[0]
raise InvalidCodeHashIndexError.new("Invalid code hash index") unless CODE_HASH_INDEXES.include?(code_hash_index)

CKB::Utils.bin_to_hex(data.slice(2..-1))
end

def self.parse_full_payload_address(address, mode: DEFAULT_MODE)
decoded_prefix, data = ConvertAddress.decode(address)
format_type = data[0].unpack("H*").first

raise InvalidPrefixError.new("Invalid prefix") if decoded_prefix != prefix(mode: mode)
raise InvalidFormatTypeError.new("Invalid format type") unless TYPES[1..-1].include?(format_type)

offset = 1
code_hash_size = 32
code_hash = "0x#{data.slice(offset..code_hash_size).unpack("H*").first}"
offset += 32
data_size = data.bytesize
args = []
while offset < data_size
arg_len = data[offset].unpack("C").first.to_i
offset += 1
arg = data[offset...offset + arg_len]
args << arg
offset += arg_len
end

["0x#{format_type}", code_hash, args.map { |item| CKB::Utils.bin_to_hex(item) }]
end

def self.parse(address, mode: DEFAULT_MODE)
_decoded_prefix, data = ConvertAddress.decode(address)
format_type = data[0].unpack("H*").first
case format_type
when "01"
parse_short_payload_address(address, mode: mode)
when "02", "04"
parse_full_payload_address(address, mode: mode)
else
raise InvalidFormatTypeError.new("Invalid format type")
end
end

def self.blake160(pubkey)
pubkey = pubkey[2..-1] if pubkey.start_with?("0x")
pubkey_bin = [pubkey].pack("H*")
hash_bin = CKB::Blake2b.digest(pubkey_bin)
Utils.bin_to_hex(hash_bin[0...20])
end

def self.hash160(pubkey)
pubkey = pubkey[2..-1] if pubkey.start_with?("0x")
pub_key_sha256 = Digest::SHA256.hexdigest(pubkey)

"0x#{Digest::RMD160.hexdigest(pub_key_sha256)}"
end

def self.from_pubkey(pubkey, mode: DEFAULT_MODE)
new(blake160(pubkey), mode: mode)
end
Expand All @@ -66,5 +153,11 @@ def self.prefix(mode: DEFAULT_MODE)
PREFIX_MAINNET
end
end

class InvalidFormatTypeError < StandardError; end
class InvalidArgsTypeError < StandardError; end
class InvalidArgSizeError < StandardError; end
class InvalidPrefixError < StandardError; end
class InvalidCodeHashIndexError < StandardError; end
end
end
31 changes: 16 additions & 15 deletions lib/ckb/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def initialize(host: CKB::RPC::DEFAULT_URL, mode: MODE::TESTNET)
secp_group_cell_transaction = genesis_block.transactions[1]
secp_group_out_point = Types::OutPoint.new(
tx_hash: secp_group_cell_transaction.hash,
index: "0"
index: 0
)

secp_cell_type_hash = system_cell_transaction.outputs[1].type.compute_hash
Expand All @@ -43,7 +43,7 @@ def initialize(host: CKB::RPC::DEFAULT_URL, mode: MODE::TESTNET)

dao_out_point = Types::OutPoint.new(
tx_hash: system_cell_transaction.hash,
index: "2"
index: 2
)
dao_cell_data = CKB::Utils.hex_to_bin(system_cell_transaction.outputs_data[2])
dao_code_hash = CKB::Blake2b.hexdigest(dao_cell_data)
Expand All @@ -65,16 +65,16 @@ def set_dao_dep(out_point, code_hash)
end

def genesis_block
@genesis_block ||= get_block_by_number("0")
@genesis_block ||= get_block_by_number(0)
end

def genesis_block_hash
@genesis_block_hash ||= get_block_hash("0")
@genesis_block_hash ||= get_block_hash(0)
end

# @return [String | Integer]
def get_block_hash(block_number)
rpc.get_block_hash(block_number.to_s)
rpc.get_block_hash(block_number)
end

# @param block_hash [String] 0x...
Expand All @@ -89,7 +89,7 @@ def get_block(block_hash)
#
# @return [CKB::Types::Block]
def get_block_by_number(block_number)
block_h = rpc.get_block_by_number(block_number.to_s)
block_h = rpc.get_block_by_number(block_number)
Types::Block.from_h(block_h)
end

Expand All @@ -101,7 +101,7 @@ def get_tip_header

# @return [String]
def get_tip_block_number
rpc.get_tip_block_number
Utils.to_int(rpc.get_tip_block_number)
end

# @param hash [String] 0x...
Expand All @@ -110,7 +110,7 @@ def get_tip_block_number
#
# @return [CKB::Types::Output[]]
def get_cells_by_lock_hash(hash, from, to)
outputs = rpc.get_cells_by_lock_hash(hash, from.to_s, to.to_s)
outputs = rpc.get_cells_by_lock_hash(hash, from, to)
outputs.map { |output| Types::Output.from_h(output) }
end

Expand All @@ -123,22 +123,23 @@ def get_transaction(tx_hash)
end

# @param out_point [CKB::Types::OutPoint]
# @param with_data [Boolean]
#
# @return [CKB::Types::CellWithStatus]
def get_live_cell(out_point)
cell_h = rpc.get_live_cell(out_point.to_h)
def get_live_cell(out_point, with_data = false)
cell_h = rpc.get_live_cell(out_point.to_h, with_data)
Types::CellWithStatus.from_h(cell_h)
end

# @param transaction [CKB::Types::Transaction]
#
# @return [String] tx_hash
def send_transaction(transaction)
rpc.send_transaction(transaction.to_h)
rpc.send_transaction(transaction.to_raw_transaction_h)
end

def compute_transaction_hash(transaction)
rpc.compute_transaction_hash(transaction.to_h)
rpc.compute_transaction_hash(transaction.to_raw_transaction_h)
end

def compute_script_hash(script)
Expand Down Expand Up @@ -194,7 +195,7 @@ def get_peers_state
#
# @return [CKB::Types::DryRunResult]
def dry_run_transaction(transaction)
result = rpc.dry_run_transaction(transaction.to_h)
result = rpc.dry_run_transaction(transaction.to_raw_transaction_h)
Types::DryRunResult.from_h(result)
end

Expand Down Expand Up @@ -245,7 +246,7 @@ def get_transactions_by_lock_hash(lock_hash, page, per, reverse_order: false)
# @param index_from [String]
#
# @return [Types::LockHashIndexState]
def index_lock_hash(lock_hash, index_from: "0")
def index_lock_hash(lock_hash, index_from: 0)
state = rpc.index_lock_hash(lock_hash, index_from: index_from)
Types::LockHashIndexState.from_h(state)
end
Expand All @@ -262,7 +263,7 @@ def get_header(block_hash)
#
# @return [CKB::Types::BlockHeader]
def get_header_by_number(block_number)
block_header_h = rpc.get_header_by_number(block_number.to_s)
block_header_h = rpc.get_header_by_number(block_number)
Types::BlockHeader.from_h(block_header_h)
end

Expand Down
Loading

0 comments on commit d3a4488

Please sign in to comment.