tapyrus 0.2.13 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82146cdd150374b76b593273e44c31f4f578d38a1b7dcabea0b0d1fd9acbbb5f
4
- data.tar.gz: 8895de33dd2b36412f509c4e35465d513d3d6c98a0bcfc0e7db241a77acd8b3b
3
+ metadata.gz: bfdff40e4807919098065d5d956383663673f20a264d0eaadaa89124467166f8
4
+ data.tar.gz: 731e768f37f843fc6a03d337e8aea349d57f23449068356348d2bef171d02a2f
5
5
  SHA512:
6
- metadata.gz: e386ac9d8578846437902e78d79b3d4419c85df861c831c92641da94d2d46a37c4793efaafa8e28a1da4466e5347fbe79f66beb0d925fe2bfc83cca1d1e90c99
7
- data.tar.gz: a34fa0709093aafb118356b7736b409c733e1185a22538f7e2ed4392dac0ac661a652a31853f652d988860ee66c8b57124815b0fc28dd795b7bea97ad44182c5
6
+ metadata.gz: 0360ede886fe0a3512ea68e212270b5d931b8c085ceb04c6790978e325bc98b1d112d74deaa80232c97109c50ad8b1175566cb04ccd5324a218563677d90fbbd
7
+ data.tar.gz: 3f6f38a994e81c0b1d5157584cf14669ee7f8be612a6e878bf7cc216995ca60255a133b1b318e6210d6328015fdd99434bde021fd124bdc44454da564023ddab
@@ -18,7 +18,7 @@ jobs:
18
18
  runs-on: ubuntu-latest
19
19
  strategy:
20
20
  matrix:
21
- ruby-version: ["2.5", "2.6", "2.7", "3.0"]
21
+ ruby-version: ["2.6", "2.7", "3.0", "3.1"]
22
22
 
23
23
  steps:
24
24
  - run: sudo apt install libleveldb-dev
@@ -26,8 +26,7 @@ jobs:
26
26
  - name: Set up Ruby
27
27
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
28
28
  # change this to (see https://github.com/ruby/setup-ruby#versioning):
29
- # uses: ruby/setup-ruby@v1
30
- uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
29
+ uses: ruby/setup-ruby@v1
31
30
  with:
32
31
  ruby-version: ${{ matrix.ruby-version }}
33
32
  bundler-cache: true # runs 'bundle install' and caches installed gems automatically
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.2
1
+ 3.1.2
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Tapyrusrb [![Build Status](https://travis-ci.org/chaintope/tapyrusrb.svg?branch=master)](https://travis-ci.org/chaintope/tapyrusrb) [![Gem Version](https://badge.fury.io/rb/tapyrus.svg)](https://badge.fury.io/rb/tapyrus) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
1
+ # Tapyrusrb [![Build Status](https://github.com/chaintope/tapyrusrb/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/chaintope/tapyrusrb/actions/workflows/ruby.yml) [![Gem Version](https://badge.fury.io/rb/tapyrus.svg)](https://badge.fury.io/rb/tapyrus) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
2
2
 
3
3
  Tapyrusrb is a Ruby implementation of [Tapyrus](https://github.com/chaintope/tapyrus-core) Protocol.
4
4
 
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tapyrus'
4
+ require 'terminal-table'
5
+
6
+ class EmptyTxChecker
7
+ def check_sig(script_sig, pubkey, script_code)
8
+ warn "Signature verification failed. You need to enter tx and input index."
9
+ exit
10
+ end
11
+ def verify_sig(sig, pubkey, digest, allow_hybrid: false)
12
+ warn "Signature verification failed. You need to enter tx and input index."
13
+ exit
14
+ end
15
+ end
16
+
17
+ def run_step(interpreter, script, chunk, index, is_redeem_script)
18
+ if chunk.pushdata?
19
+ puts "PUSH #{chunk.pushed_data.bth}"
20
+ else
21
+ puts "APPLY #{Tapyrus::Opcodes.opcode_to_name(chunk.opcode)}"
22
+ end
23
+ result = interpreter.next_step(script, chunk, index, is_redeem_script)
24
+ if result.is_a?(FalseClass)
25
+ warn "script failed. Reason: #{interpreter.error}"
26
+ exit
27
+ end
28
+ rows = interpreter.stack.map{|s|[s]}.reverse
29
+ table = Terminal::Table.new(title: 'Current Stack', rows: rows )
30
+ puts table
31
+ end
32
+
33
+ print "Enter scriptPubkey: "
34
+ script_pubkey_hex = gets.chomp
35
+ script_pubkey = Tapyrus::Script.parse_from_payload(script_pubkey_hex.htb)
36
+ puts script_pubkey unless script_pubkey_hex.empty?
37
+
38
+ print "Enter scriptSig: "
39
+ script_sig_hex = gets.chomp
40
+ script_sig = Tapyrus::Script.parse_from_payload(script_sig_hex.htb)
41
+ puts script_sig unless script_sig_hex.empty?
42
+
43
+ unless script_sig.push_only?
44
+ warn "scriptSig has non-push opcode."
45
+ puts
46
+ end
47
+
48
+ if script_pubkey_hex.empty? && script_sig.empty?
49
+ puts "Empty script."
50
+ exit
51
+ end
52
+
53
+ print "Enter tx: "
54
+ tx_hex = gets.chomp
55
+ if tx_hex.length == 0
56
+ tx_checker = EmptyTxChecker.new
57
+ else
58
+ print "Enter index of the input: "
59
+ input_index = gets.chomp
60
+ tx_checker = Tapyrus::TxChecker.new
61
+ begin
62
+ tx_checker.tx = Tapyrus::Tx.parse_from_payload(tx_hex.htb)
63
+ rescue StandardError
64
+ warn "Invalid tx data."
65
+ exit
66
+ end
67
+ if input_index.empty?
68
+ warn "Index of input missing."
69
+ exit
70
+ end
71
+ tx_checker.input_index = input_index.to_i
72
+ if (tx_checker.tx.in.size - 1) < tx_checker.input_index
73
+ warn "Tx does not have #{tx_checker.input_index}-th input."
74
+ exit
75
+ end
76
+ end
77
+
78
+ interpreter = Tapyrus::ScriptInterpreter.new(checker: tx_checker)
79
+
80
+ target_script = script_sig
81
+ is_redeem = false
82
+ interpreter.reset_params
83
+ chunks = target_script.chunks.each
84
+ chunk_index = 0
85
+ chunks_size = target_script.chunks.length
86
+ stack_copy = nil
87
+
88
+ puts "The Script is ready to be executed; you can step execution it by putting the Enter key."
89
+ print "> "
90
+ while cmd = gets.chomp
91
+ if cmd.length == 0
92
+ if chunks_size == chunk_index
93
+ if target_script == script_sig
94
+ stack_copy = interpreter.stack.dup
95
+ target_script = script_pubkey
96
+ interpreter.reset_params
97
+ chunks = target_script.chunks.each
98
+ chunk_index = 0
99
+ chunks_size = target_script.chunks.length
100
+ elsif target_script == script_pubkey
101
+ if interpreter.stack.empty? || !interpreter.cast_to_bool(interpreter.stack.last.htb)
102
+ warn "Script evaluated without error but finished with a false/empty top stack element"
103
+ exit
104
+ end
105
+ if script_pubkey.p2sh?
106
+ interpreter.stack = stack_copy
107
+ redeem_script = Tapyrus::Script.parse_from_payload(interpreter.stack.pop.htb)
108
+ puts "APPLY P2SH: #{redeem_script}"
109
+ rows = interpreter.stack.map{|s|[s]}.reverse
110
+ table = Terminal::Table.new(title: 'Current Stack', rows: rows )
111
+ puts table
112
+ target_script = redeem_script
113
+ chunks = target_script.chunks.each
114
+ chunk_index = 0
115
+ chunks_size = target_script.chunks.length
116
+ else
117
+ puts "Execution finished."
118
+ exit
119
+ end
120
+ else
121
+ puts "Execution finished."
122
+ exit
123
+ end
124
+ end
125
+ run_step(interpreter, target_script, chunks.next, chunk_index, is_redeem)
126
+ chunk_index += 1
127
+ else
128
+ puts "Put enter key to step execution or Ctrl+D to exit."
129
+ end
130
+ print "> "
131
+ end
@@ -104,7 +104,7 @@ module Tapyrus
104
104
  end
105
105
  end
106
106
 
107
- # Check this header contains upgrade aggregated publiec key.
107
+ # Check this header contains upgrade aggregated public key.
108
108
  # @return [Boolean] if contains return true, otherwise false.
109
109
  def upgrade_agg_pubkey?
110
110
  x_field_type == X_FILED_TYPES[:aggregate_pubkey]
@@ -54,7 +54,8 @@ module Tapyrus
54
54
  end
55
55
 
56
56
  def self.init(name)
57
- i = YAML.load(File.open("#{__dir__}/chainparams/#{name}.yml"))
57
+ yaml = File.open("#{__dir__}/chainparams/#{name}.yml")
58
+ i = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(yaml) : YAML.load(yaml)
58
59
  i.dust_relay_fee ||= Tapyrus::DUST_RELAY_TX_FEE
59
60
  i
60
61
  end
@@ -94,8 +94,6 @@ module Tapyrus
94
94
  # 80 bytes of data, +1 for OP_RETURN, +2 for the pushdata opcodes.
95
95
  MAX_OP_RETURN_RELAY = 83
96
96
 
97
- SIG_VERSION = [:base]
98
-
99
97
  # for script error
100
98
  SCRIPT_ERR_OK = 0
101
99
  SCRIPT_ERR_UNKNOWN_ERROR = 1
data/lib/tapyrus/ext.rb CHANGED
@@ -1,5 +1,21 @@
1
1
  module Tapyrus
2
2
  module Ext
3
3
  autoload :JsonParser, 'tapyrus/ext/json_parser'
4
+
5
+ refine Object do
6
+ def build_json
7
+ self.is_a?(Array) ? "[#{self.map { |o| o.to_h.to_json }.join(',')}]" : to_h.to_json
8
+ end
9
+
10
+ def to_h
11
+ return self if self.is_a?(String)
12
+ instance_variables.inject({}) do |result, var|
13
+ key = var.to_s
14
+ key.slice!(0) if key.start_with?('@')
15
+ value = instance_variable_get(var)
16
+ value.is_a?(Array) ? result.update(key => value.map { |v| v.to_h }) : result.update(key => value)
17
+ end
18
+ end
19
+ end
4
20
  end
5
21
  end
@@ -2,6 +2,8 @@ module Tapyrus
2
2
  module Network
3
3
  # P2P message handler used by peer connection class.
4
4
  module MessageHandler
5
+ using Tapyrus::Ext
6
+
5
7
  # handle p2p message.
6
8
  def handle(message)
7
9
  peer.last_recv = Time.now.to_i
@@ -96,7 +96,7 @@ module Tapyrus
96
96
  script = Tapyrus::Script.parse_from_payload(hex_script.htb)
97
97
  h = script.to_h
98
98
  h.delete(:hex)
99
- h[:p2sh] = script.to_p2sh.addresses.first unless script.p2sh?
99
+ h[:p2sh] = script.to_p2sh.to_addr unless script.p2sh?
100
100
  h
101
101
  rescue Exception
102
102
  raise ArgumentError.new('Script decode failed')
@@ -61,7 +61,7 @@ module Tapyrus
61
61
  end
62
62
 
63
63
  # Add color identifier to existing p2pkh or p2sh
64
- # @param [ColorIdentifier] color identifier
64
+ # @param [ColorIdentifier] color_id color identifier
65
65
  # @return [Script] CP2PKH or CP2SH script
66
66
  # @raise [ArgumentError] if color_id is nil or invalid
67
67
  # @raise [RuntimeError] if script is neither p2pkh nor p2sh
@@ -75,7 +75,6 @@ module Tapyrus
75
75
  end
76
76
 
77
77
  # Remove color identifier from cp2pkh or cp2sh
78
- # @param [ColorIdentifier] color identifier
79
78
  # @return [Script] P2PKH or P2SH script
80
79
  # @raise [RuntimeError] if script is neither cp2pkh nor cp2sh
81
80
  def remove_color
@@ -118,26 +117,18 @@ module Tapyrus
118
117
  # @param [String] addr address.
119
118
  # @return [Tapyrus::Script] parsed script.
120
119
  def self.parse_from_addr(addr)
121
- begin
122
- segwit_addr = Bech32::SegwitAddr.new(addr)
123
- raise 'Invalid hrp.' unless Tapyrus.chain_params.bech32_hrp == segwit_addr.hrp
124
- Tapyrus::Script.parse_from_payload(segwit_addr.to_script_pubkey.htb)
125
- rescue Exception => e
126
- hex, addr_version = Tapyrus.decode_base58_address(addr)
127
- case addr_version
128
- when Tapyrus.chain_params.address_version
129
- Tapyrus::Script.to_p2pkh(hex)
130
- when Tapyrus.chain_params.p2sh_version
131
- Tapyrus::Script.to_p2sh(hex)
132
- when Tapyrus.chain_params.cp2pkh_version
133
- color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
134
- Tapyrus::Script.to_cp2pkh(color, hex[66..-1])
135
- when Tapyrus.chain_params.cp2sh_version
136
- color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
137
- Tapyrus::Script.to_cp2sh(color, hex[66..-1])
138
- else
139
- throw e
140
- end
120
+ hex, addr_version = Tapyrus.decode_base58_address(addr)
121
+ case addr_version
122
+ when Tapyrus.chain_params.address_version
123
+ Tapyrus::Script.to_p2pkh(hex)
124
+ when Tapyrus.chain_params.p2sh_version
125
+ Tapyrus::Script.to_p2sh(hex)
126
+ when Tapyrus.chain_params.cp2pkh_version
127
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
128
+ Tapyrus::Script.to_cp2pkh(color, hex[66..-1])
129
+ when Tapyrus.chain_params.cp2sh_version
130
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
131
+ Tapyrus::Script.to_cp2sh(color, hex[66..-1])
141
132
  end
142
133
  end
143
134
 
@@ -189,6 +180,17 @@ module Tapyrus
189
180
  chunks.size == 0
190
181
  end
191
182
 
183
+ # Returns the address corresponding to this script. Return nil if there is no corresponding address.
184
+ # @return [String] address
185
+ def to_addr
186
+ return p2pkh_addr if p2pkh?
187
+ return p2sh_addr if p2sh?
188
+ return cp2pkh_addr if cp2pkh?
189
+ return cp2sh_addr if cp2sh?
190
+ nil
191
+ end
192
+
193
+ # @deprecated use #to_addr method.
192
194
  def addresses
193
195
  return [p2pkh_addr] if p2pkh?
194
196
  return [p2sh_addr] if p2sh?