tapyrus 0.1.0 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -15
- data/exe/tapyrusrbd +2 -2
- data/lib/openassets/util.rb +2 -4
- data/lib/schnorr.rb +83 -0
- data/lib/schnorr/signature.rb +38 -0
- data/lib/tapyrus.rb +11 -18
- data/lib/tapyrus/block.rb +3 -38
- data/lib/tapyrus/block_header.rb +70 -41
- data/lib/tapyrus/chain_params.rb +13 -36
- data/lib/tapyrus/chainparams/{regtest.yml → dev.yml} +10 -19
- data/lib/tapyrus/chainparams/{mainnet.yml → prod.yml} +7 -19
- data/lib/tapyrus/constants.rb +12 -34
- data/lib/tapyrus/errors.rb +17 -0
- data/lib/tapyrus/ext.rb +5 -0
- data/lib/tapyrus/ext/ecdsa.rb +39 -0
- data/lib/tapyrus/ext/json_parser.rb +47 -0
- data/lib/tapyrus/ext_key.rb +42 -23
- data/lib/tapyrus/key.rb +47 -40
- data/lib/tapyrus/message.rb +2 -2
- data/lib/tapyrus/message/base.rb +1 -0
- data/lib/tapyrus/message/block.rb +4 -4
- data/lib/tapyrus/message/cmpct_block.rb +3 -5
- data/lib/tapyrus/message/header_and_short_ids.rb +1 -1
- data/lib/tapyrus/message/headers.rb +1 -1
- data/lib/tapyrus/message/merkle_block.rb +1 -1
- data/lib/tapyrus/message/tx.rb +2 -2
- data/lib/tapyrus/network/peer.rb +1 -15
- data/lib/tapyrus/node/cli.rb +15 -11
- data/lib/tapyrus/node/configuration.rb +1 -1
- data/lib/tapyrus/node/spv.rb +1 -1
- data/lib/tapyrus/opcodes.rb +5 -0
- data/lib/tapyrus/out_point.rb +1 -1
- data/lib/tapyrus/rpc/request_handler.rb +7 -6
- data/lib/tapyrus/rpc/tapyrus_core_client.rb +17 -15
- data/lib/tapyrus/script/color.rb +79 -0
- data/lib/tapyrus/script/multisig.rb +0 -27
- data/lib/tapyrus/script/script.rb +74 -89
- data/lib/tapyrus/script/script_error.rb +8 -14
- data/lib/tapyrus/script/script_interpreter.rb +65 -86
- data/lib/tapyrus/script/tx_checker.rb +21 -5
- data/lib/tapyrus/secp256k1.rb +1 -0
- data/lib/tapyrus/secp256k1/native.rb +93 -20
- data/lib/tapyrus/secp256k1/rfc6979.rb +43 -0
- data/lib/tapyrus/secp256k1/ruby.rb +63 -54
- data/lib/tapyrus/store/chain_entry.rb +3 -2
- data/lib/tapyrus/store/db/level_db.rb +58 -0
- data/lib/tapyrus/store/spv_chain.rb +29 -11
- data/lib/tapyrus/tx.rb +18 -160
- data/lib/tapyrus/tx_in.rb +4 -11
- data/lib/tapyrus/tx_out.rb +2 -1
- data/lib/tapyrus/util.rb +8 -0
- data/lib/tapyrus/validation.rb +1 -6
- data/lib/tapyrus/version.rb +1 -1
- data/lib/tapyrus/wallet/account.rb +1 -0
- data/lib/tapyrus/wallet/master_key.rb +1 -0
- data/tapyrusrb.gemspec +3 -3
- metadata +44 -39
- data/lib/tapyrus/chainparams/testnet.yml +0 -41
- data/lib/tapyrus/descriptor.rb +0 -147
- data/lib/tapyrus/script_witness.rb +0 -38
    
        data/lib/tapyrus/key.rb
    CHANGED
    
    | @@ -11,6 +11,8 @@ module Tapyrus | |
| 11 11 | 
             
                SIGNATURE_SIZE = 72
         | 
| 12 12 | 
             
                COMPACT_SIGNATURE_SIZE = 65
         | 
| 13 13 |  | 
| 14 | 
            +
                SIG_ALGO = [:ecdsa, :schnorr]
         | 
| 15 | 
            +
             | 
| 14 16 | 
             
                attr_accessor :priv_key
         | 
| 15 17 | 
             
                attr_accessor :pubkey
         | 
| 16 18 | 
             
                attr_accessor :key_type
         | 
| @@ -28,7 +30,7 @@ module Tapyrus | |
| 28 30 | 
             
                # @param [Integer] key_type a key type which determine address type.
         | 
| 29 31 | 
             
                # @param [Boolean] compressed [Deprecated] whether public key is compressed.
         | 
| 30 32 | 
             
                # @return [Tapyrus::Key] a key object.
         | 
| 31 | 
            -
                def initialize(priv_key: nil, pubkey: nil, key_type: nil, compressed: true)
         | 
| 33 | 
            +
                def initialize(priv_key: nil, pubkey: nil, key_type: nil, compressed: true, allow_hybrid: false)
         | 
| 32 34 | 
             
                  puts "[Warning] Use key_type parameter instead of compressed. compressed parameter removed in the future." if key_type.nil? && !compressed.nil? && pubkey.nil?
         | 
| 33 35 | 
             
                  if key_type
         | 
| 34 36 | 
             
                    @key_type = key_type
         | 
| @@ -39,13 +41,14 @@ module Tapyrus | |
| 39 41 | 
             
                  @secp256k1_module =  Tapyrus.secp_impl
         | 
| 40 42 | 
             
                  @priv_key = priv_key
         | 
| 41 43 | 
             
                  if @priv_key
         | 
| 42 | 
            -
                    raise ArgumentError,  | 
| 44 | 
            +
                    raise ArgumentError, Errors::Messages::INVALID_PRIV_KEY unless validate_private_key_range(@priv_key)
         | 
| 43 45 | 
             
                  end
         | 
| 44 46 | 
             
                  if pubkey
         | 
| 45 47 | 
             
                    @pubkey = pubkey
         | 
| 46 48 | 
             
                  else
         | 
| 47 49 | 
             
                    @pubkey = generate_pubkey(priv_key, compressed: compressed) if priv_key
         | 
| 48 50 | 
             
                  end
         | 
| 51 | 
            +
                  raise ArgumentError, Errors::Messages::INVALID_PUBLIC_KEY unless fully_valid_pubkey?(allow_hybrid)
         | 
| 49 52 | 
             
                end
         | 
| 50 53 |  | 
| 51 54 | 
             
                # generate key pair
         | 
| @@ -63,7 +66,7 @@ module Tapyrus | |
| 63 66 | 
             
                  data = hex[2...-8].htb
         | 
| 64 67 | 
             
                  checksum = hex[-8..-1]
         | 
| 65 68 | 
             
                  raise ArgumentError, 'invalid version' unless version == Tapyrus.chain_params.privkey_version
         | 
| 66 | 
            -
                  raise ArgumentError,  | 
| 69 | 
            +
                  raise ArgumentError, Errors::Messages::INVALID_CHECKSUM unless Tapyrus.calc_checksum(version + data.bth) == checksum
         | 
| 67 70 | 
             
                  key_len = data.bytesize
         | 
| 68 71 | 
             
                  if key_len == COMPRESSED_PUBLIC_KEY_SIZE && data[-1].unpack('C').first == 1
         | 
| 69 72 | 
             
                    key_type = TYPES[:compressed]
         | 
| @@ -89,29 +92,31 @@ module Tapyrus | |
| 89 92 | 
             
                # @param [String] data a data to be signed with binary format
         | 
| 90 93 | 
             
                # @param [Boolean] low_r flag to apply low-R.
         | 
| 91 94 | 
             
                # @param [String] extra_entropy the extra entropy for rfc6979.
         | 
| 95 | 
            +
                # @param [Symbol] algo Algorithms used for verification. Either :ecdsa or :schnorr is supported. default value is :ecdsa.
         | 
| 92 96 | 
             
                # @return [String] signature data with binary format
         | 
| 93 | 
            -
                def sign(data, low_r = true, extra_entropy = nil)
         | 
| 94 | 
            -
                   | 
| 95 | 
            -
                   | 
| 96 | 
            -
             | 
| 97 | 
            -
                     | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
                     | 
| 97 | 
            +
                def sign(data, low_r = true, extra_entropy = nil, algo: :ecdsa)
         | 
| 98 | 
            +
                  raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
         | 
| 99 | 
            +
                  case algo
         | 
| 100 | 
            +
                  when :ecdsa
         | 
| 101 | 
            +
                    sign_ecdsa(data, low_r, extra_entropy)
         | 
| 102 | 
            +
                  when :schnorr
         | 
| 103 | 
            +
                    secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: algo)
         | 
| 104 | 
            +
                  else
         | 
| 105 | 
            +
                    false
         | 
| 102 106 | 
             
                  end
         | 
| 103 | 
            -
                  sig
         | 
| 104 107 | 
             
                end
         | 
| 105 108 |  | 
| 106 109 | 
             
                # verify signature using public key
         | 
| 107 110 | 
             
                # @param [String] sig signature data with binary format
         | 
| 108 111 | 
             
                # @param [String] origin original message
         | 
| 112 | 
            +
                # @param [Symbol] algo Algorithms used for verification. Either :ecdsa or :schnorr is supported. default value is :ecdsa.
         | 
| 109 113 | 
             
                # @return [Boolean] verify result
         | 
| 110 | 
            -
                def verify(sig, origin)
         | 
| 114 | 
            +
                def verify(sig, origin, algo: :ecdsa)
         | 
| 111 115 | 
             
                  return false unless valid_pubkey?
         | 
| 112 116 | 
             
                  begin
         | 
| 113 | 
            -
                     | 
| 114 | 
            -
                     | 
| 117 | 
            +
                    raise ArgumentError, "Unsupported algorithm has been specified." unless SIG_ALGO.include?(algo)
         | 
| 118 | 
            +
                    sig = ecdsa_signature_parse_der_lax(sig) if algo == :ecdsa
         | 
| 119 | 
            +
                    secp256k1_module.verify_sig(origin, sig, pubkey, algo: algo)
         | 
| 115 120 | 
             
                  rescue Exception
         | 
| 116 121 | 
             
                    false
         | 
| 117 122 | 
             
                  end
         | 
| @@ -128,18 +133,6 @@ module Tapyrus | |
| 128 133 | 
             
                  Tapyrus::Script.to_p2pkh(hash160).addresses.first
         | 
| 129 134 | 
             
                end
         | 
| 130 135 |  | 
| 131 | 
            -
                # get pay to witness pubkey hash address
         | 
| 132 | 
            -
                # @deprecated
         | 
| 133 | 
            -
                def to_p2wpkh
         | 
| 134 | 
            -
                  Tapyrus::Script.to_p2wpkh(hash160).addresses.first
         | 
| 135 | 
            -
                end
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                # get p2wpkh address nested in p2sh.
         | 
| 138 | 
            -
                # @deprecated
         | 
| 139 | 
            -
                def to_nested_p2wpkh
         | 
| 140 | 
            -
                  Tapyrus::Script.to_p2wpkh(hash160).to_p2sh.addresses.first
         | 
| 141 | 
            -
                end
         | 
| 142 | 
            -
             | 
| 143 136 | 
             
                def compressed?
         | 
| 144 137 | 
             
                  key_type != TYPES[:uncompressed]
         | 
| 145 138 | 
             
                end
         | 
| @@ -191,18 +184,24 @@ module Tapyrus | |
| 191 184 |  | 
| 192 185 | 
             
                # check +sig+ is correct der encoding.
         | 
| 193 186 | 
             
                # This function is consensus-critical since BIP66.
         | 
| 194 | 
            -
                 | 
| 195 | 
            -
             | 
| 187 | 
            +
                # @param [String] sig a signature data with binary format.
         | 
| 188 | 
            +
                # @param [Boolean] data_sig whether data signature or not.
         | 
| 189 | 
            +
                # @return [Boolean] result
         | 
| 190 | 
            +
                def self.valid_signature_encoding?(sig, data_sig = false)
         | 
| 191 | 
            +
                  num_parts = data_sig ? 8 : 9
         | 
| 192 | 
            +
                  size = data_sig ? 72 : 73
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                  return false if sig.bytesize < num_parts || sig.bytesize > size # Minimum and maximum size check
         | 
| 196 195 |  | 
| 197 196 | 
             
                  s = sig.unpack('C*')
         | 
| 198 197 |  | 
| 199 | 
            -
                  return false if s[0] != 0x30 || s[1] != s.size - 3 # A signature is of type 0x30 (compound). Make sure the length covers the entire signature.
         | 
| 198 | 
            +
                  return false if s[0] != 0x30 || s[1] != s.size - (data_sig ? 2 : 3) # A signature is of type 0x30 (compound). Make sure the length covers the entire signature.
         | 
| 200 199 |  | 
| 201 200 | 
             
                  len_r = s[3]
         | 
| 202 201 | 
             
                  return false if 5 + len_r >= s.size # Make sure the length of the S element is still inside the signature.
         | 
| 203 202 |  | 
| 204 203 | 
             
                  len_s = s[5 + len_r]
         | 
| 205 | 
            -
                  return false unless len_r + len_s + 7 == s.size #Verify that the length of the signature matches the sum of the length of the elements.
         | 
| 204 | 
            +
                  return false unless len_r + len_s + (data_sig ? 6 : 7) == s.size #Verify that the length of the signature matches the sum of the length of the elements.
         | 
| 206 205 |  | 
| 207 206 | 
             
                  return false unless s[2] == 0x02 # Check whether the R element is an integer.
         | 
| 208 207 |  | 
| @@ -225,14 +224,8 @@ module Tapyrus | |
| 225 224 | 
             
                end
         | 
| 226 225 |  | 
| 227 226 | 
             
                # fully validate whether this is a valid public key (more expensive than IsValid())
         | 
| 228 | 
            -
                def fully_valid_pubkey?
         | 
| 229 | 
            -
                   | 
| 230 | 
            -
                  begin
         | 
| 231 | 
            -
                    point = ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1)
         | 
| 232 | 
            -
                    ECDSA::Group::Secp256k1.valid_public_key?(point)
         | 
| 233 | 
            -
                  rescue ECDSA::Format::DecodeError
         | 
| 234 | 
            -
                    false
         | 
| 235 | 
            -
                  end
         | 
| 227 | 
            +
                def fully_valid_pubkey?(allow_hybrid = false)
         | 
| 228 | 
            +
                  valid_pubkey? && secp256k1_module.parse_ec_pubkey?(pubkey, allow_hybrid)
         | 
| 236 229 | 
             
                end
         | 
| 237 230 |  | 
| 238 231 | 
             
                private
         | 
| @@ -291,6 +284,20 @@ module Tapyrus | |
| 291 284 | 
             
                  sig[3].bth.to_i(16) == 0x20 && sig[4].bth.to_i(16) < 0x80
         | 
| 292 285 | 
             
                end
         | 
| 293 286 |  | 
| 287 | 
            +
                # generate ecdsa signature
         | 
| 288 | 
            +
                def sign_ecdsa(data, low_r, extra_entropy)
         | 
| 289 | 
            +
                  sig = secp256k1_module.sign_data(data, priv_key, extra_entropy, algo: :ecdsa)
         | 
| 290 | 
            +
                  if low_r && !sig_has_low_r?(sig)
         | 
| 291 | 
            +
                    counter = 1
         | 
| 292 | 
            +
                    until sig_has_low_r?(sig)
         | 
| 293 | 
            +
                      extra_entropy = [counter].pack('I*').bth.ljust(64, '0').htb
         | 
| 294 | 
            +
                      sig = secp256k1_module.sign_data(data, priv_key, extra_entropy,  algo: :ecdsa)
         | 
| 295 | 
            +
                      counter += 1
         | 
| 296 | 
            +
                    end
         | 
| 297 | 
            +
                  end
         | 
| 298 | 
            +
                  sig
         | 
| 299 | 
            +
                end
         | 
| 300 | 
            +
             | 
| 294 301 | 
             
              end
         | 
| 295 302 |  | 
| 296 303 | 
             
            end
         | 
    
        data/lib/tapyrus/message.rb
    CHANGED
    
    | @@ -45,13 +45,13 @@ module Tapyrus | |
| 45 45 | 
             
                    network: 1 << 0,  # the node is capable of serving the block chain. It is currently set by all Bitcoin Core node, and is unset by SPV clients or other peers that just want network services but don't provide them.
         | 
| 46 46 | 
             
                    # getutxo: 1 << 1, # BIP-64. not implemented in Bitcoin Core.
         | 
| 47 47 | 
             
                    bloom: 1 << 2,    # the node is capable and willing to handle bloom-filtered connections. Bitcoin Core node used to support this by default, without advertising this bit, but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
         | 
| 48 | 
            -
                    witness: 1 << 3,  # the node can be asked for blocks and transactions including witness data.
         | 
| 48 | 
            +
                    #witness: 1 << 3,  # the node can be asked for blocks and transactions including witness data.
         | 
| 49 49 | 
             
                    # xthin: 1 << 4 # support Xtreme Thinblocks. not implemented in Bitcoin Core
         | 
| 50 50 | 
             
                }
         | 
| 51 51 |  | 
| 52 52 | 
             
                # DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:network] | SERVICE_FLAGS[:bloom] | SERVICE_FLAGS[:witness]
         | 
| 53 53 |  | 
| 54 | 
            -
                DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:none] | 
| 54 | 
            +
                DEFAULT_SERVICE_FLAGS = SERVICE_FLAGS[:none]
         | 
| 55 55 |  | 
| 56 56 | 
             
                DEFAULT_STOP_HASH = "00"*32
         | 
| 57 57 |  | 
    
        data/lib/tapyrus/message/base.rb
    CHANGED
    
    
| @@ -11,15 +11,15 @@ module Tapyrus | |
| 11 11 |  | 
| 12 12 | 
             
                  COMMAND = 'block'
         | 
| 13 13 |  | 
| 14 | 
            -
                  def initialize(header, transactions = [] | 
| 14 | 
            +
                  def initialize(header, transactions = [])
         | 
| 15 15 | 
             
                    @header = header
         | 
| 16 16 | 
             
                    @transactions = transactions
         | 
| 17 | 
            -
                    @use_segwit =  | 
| 17 | 
            +
                    @use_segwit = false
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| 20 20 | 
             
                  def self.parse_from_payload(payload)
         | 
| 21 21 | 
             
                    buf = StringIO.new(payload)
         | 
| 22 | 
            -
                    header = Tapyrus::BlockHeader.parse_from_payload(buf | 
| 22 | 
            +
                    header = Tapyrus::BlockHeader.parse_from_payload(buf)
         | 
| 23 23 | 
             
                    transactions = []
         | 
| 24 24 | 
             
                    unless buf.eof?
         | 
| 25 25 | 
             
                      tx_count = Tapyrus.unpack_var_int_from_io(buf)
         | 
| @@ -32,7 +32,7 @@ module Tapyrus | |
| 32 32 |  | 
| 33 33 | 
             
                  def to_payload
         | 
| 34 34 | 
             
                    header.to_payload << Tapyrus.pack_var_int(transactions.size) <<
         | 
| 35 | 
            -
                      transactions.map | 
| 35 | 
            +
                      transactions.map(&:to_payload).join
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| 38 38 | 
             
                  # generate Tapyrus::Block object.
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            module Tapyrus
         | 
| 2 2 | 
             
              module Message
         | 
| 3 3 |  | 
| 4 | 
            -
                # cmpctblock message
         | 
| 4 | 
            +
                # cmpctblock message. support only version 1.
         | 
| 5 5 | 
             
                # https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
         | 
| 6 6 | 
             
                class CmpctBlock < Base
         | 
| 7 7 |  | 
| @@ -15,14 +15,12 @@ module Tapyrus | |
| 15 15 |  | 
| 16 16 | 
             
                  # generate CmpctBlock from Block data.
         | 
| 17 17 | 
             
                  # @param [Tapyrus::Block] block the block to generate CmpctBlock.
         | 
| 18 | 
            -
                  # @param [Integer] version Compact Block version specified by sendcmpct message.
         | 
| 19 18 | 
             
                  # @param [Integer] nonce
         | 
| 20 19 | 
             
                  # @return [Tapyrus::Message::CmpctBlock]
         | 
| 21 | 
            -
                  def self.from_block(block,  | 
| 22 | 
            -
                    raise 'Unsupported version.' unless [1, 2].include?(version)
         | 
| 20 | 
            +
                  def self.from_block(block, nonce = SecureRandom.hex(8).to_i(16))
         | 
| 23 21 | 
             
                    h = HeaderAndShortIDs.new(block.header, nonce)
         | 
| 24 22 | 
             
                    block.transactions[1..-1].each do |tx|
         | 
| 25 | 
            -
                      h.short_ids << h.short_id( | 
| 23 | 
            +
                      h.short_ids << h.short_id(tx.txid)
         | 
| 26 24 | 
             
                    end
         | 
| 27 25 | 
             
                    h.prefilled_txn << PrefilledTx.new(0, block.transactions.first)
         | 
| 28 26 | 
             
                    self.new(h)
         | 
| @@ -21,7 +21,7 @@ module Tapyrus | |
| 21 21 |  | 
| 22 22 | 
             
                  def self.parse_from_payload(payload)
         | 
| 23 23 | 
             
                    buf = StringIO.new(payload)
         | 
| 24 | 
            -
                    header = Tapyrus::BlockHeader.parse_from_payload(buf | 
| 24 | 
            +
                    header = Tapyrus::BlockHeader.parse_from_payload(buf)
         | 
| 25 25 | 
             
                    nonce = buf.read(8).unpack('q*').first
         | 
| 26 26 | 
             
                    short_ids_len = Tapyrus.unpack_var_int_from_io(buf)
         | 
| 27 27 | 
             
                    short_ids = short_ids_len.times.map do
         | 
| @@ -19,7 +19,7 @@ module Tapyrus | |
| 19 19 | 
             
                    header_count = Tapyrus.unpack_var_int_from_io(buf)
         | 
| 20 20 | 
             
                    h = new
         | 
| 21 21 | 
             
                    header_count.times do
         | 
| 22 | 
            -
                      h.headers << Tapyrus::BlockHeader.parse_from_payload(buf | 
| 22 | 
            +
                      h.headers << Tapyrus::BlockHeader.parse_from_payload(buf)
         | 
| 23 23 | 
             
                      buf.read(1) # read tx count 0x00 (headers message doesn't include any tx.)
         | 
| 24 24 | 
             
                    end
         | 
| 25 25 | 
             
                    h
         | 
| @@ -19,7 +19,7 @@ module Tapyrus | |
| 19 19 | 
             
                  def self.parse_from_payload(payload)
         | 
| 20 20 | 
             
                    m = new
         | 
| 21 21 | 
             
                    buf = StringIO.new(payload)
         | 
| 22 | 
            -
                    m.header = Tapyrus::BlockHeader.parse_from_payload(buf | 
| 22 | 
            +
                    m.header = Tapyrus::BlockHeader.parse_from_payload(buf)
         | 
| 23 23 | 
             
                    m.tx_count = buf.read(4).unpack('V').first
         | 
| 24 24 | 
             
                    hash_count = Tapyrus.unpack_var_int_from_io(buf)
         | 
| 25 25 | 
             
                    hash_count.times do
         | 
    
        data/lib/tapyrus/message/tx.rb
    CHANGED
    
    | @@ -17,11 +17,11 @@ module Tapyrus | |
| 17 17 |  | 
| 18 18 | 
             
                  def self.parse_from_payload(payload)
         | 
| 19 19 | 
             
                    tx = Tapyrus::Tx.parse_from_payload(payload)
         | 
| 20 | 
            -
                    new(tx | 
| 20 | 
            +
                    new(tx)
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 23 | 
             
                  def to_payload
         | 
| 24 | 
            -
                     | 
| 24 | 
            +
                    tx.to_payload
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 27 | 
             
                end
         | 
    
        data/lib/tapyrus/network/peer.rb
    CHANGED
    
    | @@ -99,21 +99,7 @@ module Tapyrus | |
| 99 99 |  | 
| 100 100 | 
             
                  # broadcast tx.
         | 
| 101 101 | 
             
                  def broadcast_tx(tx)
         | 
| 102 | 
            -
                    conn.send_message(Tapyrus::Message::Tx.new(tx | 
| 103 | 
            -
                  end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                  # check the remote peer support witness.
         | 
| 106 | 
            -
                  def support_witness?
         | 
| 107 | 
            -
                    return false unless remote_version
         | 
| 108 | 
            -
                    remote_version.services & Tapyrus::Message::SERVICE_FLAGS[:witness] > 0
         | 
| 109 | 
            -
                  end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                  # check the remote peer supports compact block.
         | 
| 112 | 
            -
                  def support_cmpct?
         | 
| 113 | 
            -
                    return false if remote_version.version < Tapyrus::Message::VERSION[:compact]
         | 
| 114 | 
            -
                    return true unless local_version.services & Tapyrus::Message::SERVICE_FLAGS[:witness] > 0
         | 
| 115 | 
            -
                    return false unless support_witness?
         | 
| 116 | 
            -
                    remote_version.version >= Tapyrus::Message::VERSION[:compact_witness]
         | 
| 102 | 
            +
                    conn.send_message(Tapyrus::Message::Tx.new(tx))
         | 
| 117 103 | 
             
                  end
         | 
| 118 104 |  | 
| 119 105 | 
             
                  # get peer's block type.
         | 
    
        data/lib/tapyrus/node/cli.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            require ' | 
| 1 | 
            +
            require 'net/http'
         | 
| 2 2 | 
             
            require 'thor'
         | 
| 3 3 | 
             
            require 'json'
         | 
| 4 4 |  | 
| @@ -7,7 +7,7 @@ module Tapyrus | |
| 7 7 |  | 
| 8 8 | 
             
                class CLI < Thor
         | 
| 9 9 |  | 
| 10 | 
            -
                  class_option :network, aliases: '-n', default: : | 
| 10 | 
            +
                  class_option :network, aliases: '-n', default: :prod
         | 
| 11 11 |  | 
| 12 12 | 
             
                  desc 'getblockchaininfo', 'Returns an object containing various state info regarding blockchain processing.'
         | 
| 13 13 | 
             
                  def getblockchaininfo
         | 
| @@ -92,15 +92,19 @@ module Tapyrus | |
| 92 92 | 
             
                        :id => 'jsonrpc'
         | 
| 93 93 | 
             
                    }
         | 
| 94 94 | 
             
                    begin
         | 
| 95 | 
            -
                       | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 95 | 
            +
                      uri = URI.parse(config.server_url)
         | 
| 96 | 
            +
                      http = Net::HTTP.new(uri.hostname, uri.port)
         | 
| 97 | 
            +
                      http.use_ssl = uri.scheme === "https"
         | 
| 98 | 
            +
                      request = Net::HTTP::Post.new('/')
         | 
| 99 | 
            +
                      request.content_type = 'application/json'
         | 
| 100 | 
            +
                      request.body = data.to_json
         | 
| 101 | 
            +
                      response = http.request(request)
         | 
| 102 | 
            +
                      body = response.body
         | 
| 103 | 
            +
                      begin
         | 
| 104 | 
            +
                        json = JSON.parse(body.to_str)
         | 
| 105 | 
            +
                        puts JSON.pretty_generate(json)
         | 
| 106 | 
            +
                      rescue Exception
         | 
| 107 | 
            +
                        puts body.to_str
         | 
| 104 108 | 
             
                      end
         | 
| 105 109 | 
             
                    rescue Exception => e
         | 
| 106 110 | 
             
                      puts e.message
         | 
| @@ -8,7 +8,7 @@ module Tapyrus | |
| 8 8 |  | 
| 9 9 | 
             
                  def initialize(opts = {})
         | 
| 10 10 | 
             
                    # TODO apply configuration file.
         | 
| 11 | 
            -
                    opts[:network] = : | 
| 11 | 
            +
                    opts[:network] = :prod unless opts[:network]
         | 
| 12 12 | 
             
                    opts[:relay] = false unless opts[:relay]
         | 
| 13 13 | 
             
                    Tapyrus.chain_params = opts[:network]
         | 
| 14 14 |  | 
    
        data/lib/tapyrus/node/spv.rb
    CHANGED
    
    
    
        data/lib/tapyrus/opcodes.rb
    CHANGED
    
    | @@ -141,6 +141,11 @@ module Tapyrus | |
| 141 141 | 
             
                OP_PUBKEY = 0xfe
         | 
| 142 142 | 
             
                OP_INVALIDOPCODE = 0xff
         | 
| 143 143 |  | 
| 144 | 
            +
                # tapyrus extension
         | 
| 145 | 
            +
                OP_CHECKDATASIG = 0xba
         | 
| 146 | 
            +
                OP_CHECKDATASIGVERIFY = 0xbb
         | 
| 147 | 
            +
                OP_COLOR = 0xbc
         | 
| 148 | 
            +
             | 
| 144 149 | 
             
                DUPLICATE_KEY = [:OP_NOP2, :OP_NOP3]
         | 
| 145 150 | 
             
                OPCODES_MAP = Hash[*(constants.grep(/^OP_/) - [:OP_NOP2, :OP_NOP3, :OP_CHECKLOCKTIMEVERIFY, :OP_CHECKSEQUENCEVERIFY]).map { |c| [const_get(c), c.to_s] }.flatten]
         | 
| 146 151 | 
             
                NAME_MAP = Hash[*constants.grep(/^OP_/).map { |c| [c.to_s, const_get(c)] }.flatten]
         | 
    
        data/lib/tapyrus/out_point.rb
    CHANGED
    
    
| @@ -11,7 +11,6 @@ module Tapyrus | |
| 11 11 | 
             
                    best_block = node.chain.latest_block
         | 
| 12 12 | 
             
                    h[:headers] = best_block.height
         | 
| 13 13 | 
             
                    h[:bestblockhash] = best_block.header.block_id
         | 
| 14 | 
            -
                    h[:chainwork] = best_block.header.work
         | 
| 15 14 | 
             
                    h[:mediantime] = node.chain.mtp(best_block.block_hash)
         | 
| 16 15 | 
             
                    h
         | 
| 17 16 | 
             
                  end
         | 
| @@ -31,18 +30,20 @@ module Tapyrus | |
| 31 30 | 
             
                      {
         | 
| 32 31 | 
             
                          hash: block_id,
         | 
| 33 32 | 
             
                          height: entry.height,
         | 
| 34 | 
            -
                           | 
| 35 | 
            -
                           | 
| 33 | 
            +
                          features: entry.header.features,
         | 
| 34 | 
            +
                          featuresHex: entry.header.features.to_even_length_hex.ljust(8, '0'),
         | 
| 36 35 | 
             
                          merkleroot: entry.header.merkle_root.rhex,
         | 
| 36 | 
            +
                          immutablemerkleroot: entry.header.im_merkle_root.rhex,
         | 
| 37 37 | 
             
                          time: entry.header.time,
         | 
| 38 38 | 
             
                          mediantime: node.chain.mtp(block_hash),
         | 
| 39 | 
            -
                           | 
| 40 | 
            -
                           | 
| 39 | 
            +
                          xfield_type: entry.header.x_field_type,
         | 
| 40 | 
            +
                          xfield: entry.header.x_field,
         | 
| 41 | 
            +
                          proof: entry.header.proof,
         | 
| 41 42 | 
             
                          previousblockhash: entry.prev_hash.rhex,
         | 
| 42 43 | 
             
                          nextblockhash: node.chain.next_hash(block_hash).rhex
         | 
| 43 44 | 
             
                      }
         | 
| 44 45 | 
             
                    else
         | 
| 45 | 
            -
                      entry.header. | 
| 46 | 
            +
                      entry.header.to_hex
         | 
| 46 47 | 
             
                    end
         | 
| 47 48 | 
             
                  end
         | 
| 48 49 |  | 
| @@ -1,15 +1,16 @@ | |
| 1 | 
            -
            require ' | 
| 1 | 
            +
            require 'net/http'
         | 
| 2 | 
            +
            require 'json/pure'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Tapyrus
         | 
| 4 5 | 
             
              module RPC
         | 
| 5 6 |  | 
| 6 | 
            -
                # Client implementation for RPC to  | 
| 7 | 
            +
                # Client implementation for RPC to Tapyrus Core.
         | 
| 7 8 | 
             
                #
         | 
| 8 9 | 
             
                # [Usage]
         | 
| 9 10 | 
             
                # config = {schema: 'http', host: 'localhost', port: 18332, user: 'xxx', password: 'yyy'}
         | 
| 10 | 
            -
                # client = Tapyrus::RPC:: | 
| 11 | 
            +
                # client = Tapyrus::RPC::TapyrusCoreClient.new(config)
         | 
| 11 12 | 
             
                #
         | 
| 12 | 
            -
                # You can execute the CLI command supported by  | 
| 13 | 
            +
                # You can execute the CLI command supported by Tapyrus Core as follows:
         | 
| 13 14 | 
             
                #
         | 
| 14 15 | 
             
                # client.listunspent
         | 
| 15 16 | 
             
                # client.getblockchaininfo
         | 
| @@ -53,17 +54,18 @@ module Tapyrus | |
| 53 54 | 
             
                        :params => params,
         | 
| 54 55 | 
             
                        :id => 'jsonrpc'
         | 
| 55 56 | 
             
                    }
         | 
| 56 | 
            -
                     | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
                     | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
                     | 
| 66 | 
            -
             | 
| 57 | 
            +
                    uri = URI.parse(server_url)
         | 
| 58 | 
            +
                    http = Net::HTTP.new(uri.hostname, uri.port)
         | 
| 59 | 
            +
                    http.use_ssl = uri.scheme === "https"
         | 
| 60 | 
            +
                    request = Net::HTTP::Post.new(uri.path.empty? ? '/' : uri.path)
         | 
| 61 | 
            +
                    request.basic_auth(uri.user, uri.password)
         | 
| 62 | 
            +
                    request.content_type = 'application/json'
         | 
| 63 | 
            +
                    request.body = data.to_json
         | 
| 64 | 
            +
                    response = http.request(request)
         | 
| 65 | 
            +
                    body = response.body
         | 
| 66 | 
            +
                    response = Tapyrus::Ext::JsonParser.new(body.gsub(/\\u([\da-fA-F]{4})/) { [$1].pack('H*').unpack('n*').pack('U*').encode('ISO-8859-1').force_encoding('UTF-8') }).parse
         | 
| 67 | 
            +
                    raise response['error'].to_json if response['error']
         | 
| 68 | 
            +
                    response['result']
         | 
| 67 69 | 
             
                  end
         | 
| 68 70 |  | 
| 69 71 | 
             
                end
         |