tapyrus 0.1.0

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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +12 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +100 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/exe/tapyrusrb-cli +5 -0
  15. data/exe/tapyrusrbd +41 -0
  16. data/lib/openassets/marker_output.rb +20 -0
  17. data/lib/openassets/payload.rb +54 -0
  18. data/lib/openassets/util.rb +28 -0
  19. data/lib/openassets.rb +9 -0
  20. data/lib/tapyrus/base58.rb +38 -0
  21. data/lib/tapyrus/block.rb +77 -0
  22. data/lib/tapyrus/block_header.rb +88 -0
  23. data/lib/tapyrus/bloom_filter.rb +78 -0
  24. data/lib/tapyrus/chain_params.rb +90 -0
  25. data/lib/tapyrus/chainparams/mainnet.yml +41 -0
  26. data/lib/tapyrus/chainparams/regtest.yml +38 -0
  27. data/lib/tapyrus/chainparams/testnet.yml +41 -0
  28. data/lib/tapyrus/constants.rb +195 -0
  29. data/lib/tapyrus/descriptor.rb +147 -0
  30. data/lib/tapyrus/ext_key.rb +337 -0
  31. data/lib/tapyrus/key.rb +296 -0
  32. data/lib/tapyrus/key_path.rb +26 -0
  33. data/lib/tapyrus/logger.rb +42 -0
  34. data/lib/tapyrus/merkle_tree.rb +149 -0
  35. data/lib/tapyrus/message/addr.rb +35 -0
  36. data/lib/tapyrus/message/base.rb +28 -0
  37. data/lib/tapyrus/message/block.rb +46 -0
  38. data/lib/tapyrus/message/block_transaction_request.rb +45 -0
  39. data/lib/tapyrus/message/block_transactions.rb +31 -0
  40. data/lib/tapyrus/message/block_txn.rb +27 -0
  41. data/lib/tapyrus/message/cmpct_block.rb +42 -0
  42. data/lib/tapyrus/message/error.rb +10 -0
  43. data/lib/tapyrus/message/fee_filter.rb +27 -0
  44. data/lib/tapyrus/message/filter_add.rb +28 -0
  45. data/lib/tapyrus/message/filter_clear.rb +17 -0
  46. data/lib/tapyrus/message/filter_load.rb +39 -0
  47. data/lib/tapyrus/message/get_addr.rb +17 -0
  48. data/lib/tapyrus/message/get_block_txn.rb +27 -0
  49. data/lib/tapyrus/message/get_blocks.rb +29 -0
  50. data/lib/tapyrus/message/get_data.rb +21 -0
  51. data/lib/tapyrus/message/get_headers.rb +28 -0
  52. data/lib/tapyrus/message/header_and_short_ids.rb +57 -0
  53. data/lib/tapyrus/message/headers.rb +35 -0
  54. data/lib/tapyrus/message/headers_parser.rb +24 -0
  55. data/lib/tapyrus/message/inv.rb +21 -0
  56. data/lib/tapyrus/message/inventories_parser.rb +23 -0
  57. data/lib/tapyrus/message/inventory.rb +51 -0
  58. data/lib/tapyrus/message/mem_pool.rb +17 -0
  59. data/lib/tapyrus/message/merkle_block.rb +42 -0
  60. data/lib/tapyrus/message/network_addr.rb +63 -0
  61. data/lib/tapyrus/message/not_found.rb +21 -0
  62. data/lib/tapyrus/message/ping.rb +30 -0
  63. data/lib/tapyrus/message/pong.rb +26 -0
  64. data/lib/tapyrus/message/prefilled_tx.rb +29 -0
  65. data/lib/tapyrus/message/reject.rb +46 -0
  66. data/lib/tapyrus/message/send_cmpct.rb +43 -0
  67. data/lib/tapyrus/message/send_headers.rb +16 -0
  68. data/lib/tapyrus/message/tx.rb +30 -0
  69. data/lib/tapyrus/message/ver_ack.rb +17 -0
  70. data/lib/tapyrus/message/version.rb +69 -0
  71. data/lib/tapyrus/message.rb +70 -0
  72. data/lib/tapyrus/mnemonic/wordlist/chinese_simplified.txt +2048 -0
  73. data/lib/tapyrus/mnemonic/wordlist/chinese_traditional.txt +2048 -0
  74. data/lib/tapyrus/mnemonic/wordlist/english.txt +2048 -0
  75. data/lib/tapyrus/mnemonic/wordlist/french.txt +2048 -0
  76. data/lib/tapyrus/mnemonic/wordlist/italian.txt +2048 -0
  77. data/lib/tapyrus/mnemonic/wordlist/japanese.txt +2048 -0
  78. data/lib/tapyrus/mnemonic/wordlist/spanish.txt +2048 -0
  79. data/lib/tapyrus/mnemonic.rb +77 -0
  80. data/lib/tapyrus/network/connection.rb +73 -0
  81. data/lib/tapyrus/network/message_handler.rb +241 -0
  82. data/lib/tapyrus/network/peer.rb +223 -0
  83. data/lib/tapyrus/network/peer_discovery.rb +42 -0
  84. data/lib/tapyrus/network/pool.rb +135 -0
  85. data/lib/tapyrus/network.rb +13 -0
  86. data/lib/tapyrus/node/cli.rb +112 -0
  87. data/lib/tapyrus/node/configuration.rb +38 -0
  88. data/lib/tapyrus/node/spv.rb +79 -0
  89. data/lib/tapyrus/node.rb +7 -0
  90. data/lib/tapyrus/opcodes.rb +178 -0
  91. data/lib/tapyrus/out_point.rb +44 -0
  92. data/lib/tapyrus/rpc/http_server.rb +65 -0
  93. data/lib/tapyrus/rpc/request_handler.rb +150 -0
  94. data/lib/tapyrus/rpc/tapyrus_core_client.rb +72 -0
  95. data/lib/tapyrus/rpc.rb +7 -0
  96. data/lib/tapyrus/script/multisig.rb +92 -0
  97. data/lib/tapyrus/script/script.rb +551 -0
  98. data/lib/tapyrus/script/script_error.rb +111 -0
  99. data/lib/tapyrus/script/script_interpreter.rb +668 -0
  100. data/lib/tapyrus/script/tx_checker.rb +81 -0
  101. data/lib/tapyrus/script_witness.rb +38 -0
  102. data/lib/tapyrus/secp256k1/native.rb +174 -0
  103. data/lib/tapyrus/secp256k1/ruby.rb +123 -0
  104. data/lib/tapyrus/secp256k1.rb +12 -0
  105. data/lib/tapyrus/slip39/share.rb +122 -0
  106. data/lib/tapyrus/slip39/sss.rb +245 -0
  107. data/lib/tapyrus/slip39/wordlist/english.txt +1024 -0
  108. data/lib/tapyrus/slip39.rb +93 -0
  109. data/lib/tapyrus/store/chain_entry.rb +67 -0
  110. data/lib/tapyrus/store/db/level_db.rb +98 -0
  111. data/lib/tapyrus/store/db.rb +9 -0
  112. data/lib/tapyrus/store/spv_chain.rb +101 -0
  113. data/lib/tapyrus/store.rb +9 -0
  114. data/lib/tapyrus/tx.rb +347 -0
  115. data/lib/tapyrus/tx_in.rb +89 -0
  116. data/lib/tapyrus/tx_out.rb +74 -0
  117. data/lib/tapyrus/util.rb +133 -0
  118. data/lib/tapyrus/validation.rb +115 -0
  119. data/lib/tapyrus/version.rb +3 -0
  120. data/lib/tapyrus/wallet/account.rb +151 -0
  121. data/lib/tapyrus/wallet/base.rb +162 -0
  122. data/lib/tapyrus/wallet/db.rb +81 -0
  123. data/lib/tapyrus/wallet/master_key.rb +110 -0
  124. data/lib/tapyrus/wallet.rb +8 -0
  125. data/lib/tapyrus.rb +219 -0
  126. data/tapyrusrb.conf.sample +0 -0
  127. data/tapyrusrb.gemspec +47 -0
  128. metadata +451 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 73863e0b35030aee45baa96661f5bbd0322e78381be022d8372e620f8cd8668c
4
+ data.tar.gz: 3f6378420bb9940a4829e378bb9975c67f5e5c5b61e4c5e077d85f83e0f59715
5
+ SHA512:
6
+ metadata.gz: 5ffa34b251d363ade9355430980d50d233c104071b15f46535fee2009b8826f4b163891e384cec997b72e2680387cd3d200b55a41c4ebda8c359fdf6f965f091
7
+ data.tar.gz: c3860a9b13c2f43ef55b47cb985eb9467d5c4fdf9f1436b6c0e97b9a1b04a2ecdcd726e0103baa5ccd302753cc460f0240c0cd76c32cc08347e46e997e0ec7d6
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ bitcoinrbd.yml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ tapyrusrb
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.3
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.6
4
+ - 2.5.5
5
+ - 2.6.3
6
+ addons:
7
+ apt:
8
+ packages:
9
+ - libleveldb-dev
10
+ bundler_args: --jobs=2
11
+ script:
12
+ - bundle exec rake spec
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at azuchi@haw.co.jp. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tapyrusrb.gemspec
4
+ gemspec
5
+
6
+ gem 'parallel_tests'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017-2019 HAW International, Inc. / chaintope, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,100 @@
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)
2
+
3
+
4
+ Tapyrusrb is a Ruby implementation of [Tapyrus](https://github.com/chaintope/tapyrus-core) Protocol.
5
+
6
+ NOTE: Tapyrusrb work in progress, and there is a possibility of incompatible change.
7
+
8
+ ## Features
9
+
10
+ Tapyrusrb supports following feature:
11
+
12
+ * Tapyrus script interpreter
13
+ * De/serialization of Tapyrus protocol network messages
14
+ * De/serialization of blocks and transactions
15
+ * Key generation and verification for ECDSA, including [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) supports.
16
+ * ECDSA signature(RFC6979 -Deterministic ECDSA, LOW-S, LOW-R support)
17
+ * [WIP] SPV node
18
+ * [WIP] 0ff-chain protocol
19
+
20
+ ## Requirements
21
+
22
+ ### use Node implementation
23
+
24
+ If you use node features, please install level DB as follows.
25
+
26
+ #### install LevelDB
27
+
28
+ * for Ubuntu
29
+
30
+ $ sudo apt-get install libleveldb-dev
31
+
32
+ + for Mac
33
+
34
+ $ brew install leveldb
35
+
36
+ and put `leveldb-native` in your Gemfile and run bundle install.
37
+
38
+ ```
39
+ gem leveldb-native
40
+ ```
41
+
42
+ ## Installation
43
+
44
+ Add this line to your application's Gemfile:
45
+
46
+ ```ruby
47
+ gem 'tapyrus'
48
+ ```
49
+
50
+ And then execute:
51
+
52
+ $ bundle
53
+
54
+ Or install it yourself as:
55
+
56
+ $ gem install tapyrus
57
+
58
+ And then add to your .rb file:
59
+
60
+ require 'tapyrus'
61
+
62
+ ## Usage
63
+
64
+ ### Chain selection
65
+
66
+ The parameters of the blockchain are managed by `Tapyrus::ChainParams`. Switch chain parameters as follows:
67
+
68
+ * mainnet
69
+
70
+ ```ruby
71
+ Tapyrus.chain_params = :mainnet
72
+ ```
73
+
74
+ This parameter is described in https://github.com/chaintope/tapyrusrb/blob/master/lib/tapyrus/chainparams/mainnet.yml.
75
+
76
+ * testnet
77
+
78
+ ```ruby
79
+ Tapyrus.chain_params = :testnet
80
+ ```
81
+
82
+ This parameter is described in https://github.com/chaintope/tapyrusrb/blob/master/lib/tapyrus/chainparams/testnet.yml.
83
+
84
+ * regtest
85
+
86
+ ```ruby
87
+ Tapyrus.chain_params = :regtest
88
+ ```
89
+
90
+ This parameter is described in https://github.com/chaintope/tapyrusrb/blob/master/lib/tapyrus/chainparams/regtest.yml.
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/tapyrusrb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
95
+
96
+
97
+ ## License
98
+
99
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
100
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tapyrus"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/tapyrusrb-cli ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tapyrus'
4
+
5
+ Tapyrus::Node::CLI.start(ARGV)
data/exe/tapyrusrbd ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ require 'thor'
3
+ require 'tapyrus'
4
+ require 'daemon_spawn'
5
+
6
+ class TapyrusDaemon < DaemonSpawn::Base
7
+
8
+ def start(args)
9
+ puts "Tapyrusrb daemon start : #{Time.now}"
10
+ conf = Tapyrus::Node::Configuration.new(network: args.first[:network])
11
+ node = Tapyrus::Node::SPV.new(conf)
12
+ node.run
13
+ end
14
+
15
+ end
16
+
17
+ class Tapyrusrbd < Thor
18
+
19
+ class_option :network, aliases: '-n', default: :mainnet
20
+
21
+ desc 'start', 'start tapyrusrb daemon.'
22
+ def start
23
+ network = options['network'] ? options['network'].to_sym : :mainnet
24
+ Tapyrus.chain_params = network
25
+ FileUtils.mkdir_p(Tapyrus.base_dir)
26
+ execute_daemon(['start', network: network])
27
+ end
28
+
29
+ private
30
+
31
+ def execute_daemon(cmd_args)
32
+ TapyrusDaemon.spawn!({working_dir: Tapyrus.base_dir,
33
+ log_file: "#{Tapyrus.base_dir}/log/tapyrusrbd.log",
34
+ pid_file: "#{Tapyrus.base_dir}/tapyrusrbd.pid",
35
+ sync_log: true,
36
+ singleton: true}, cmd_args)
37
+ end
38
+
39
+ end
40
+
41
+ Tapyrusrbd.start(ARGV)
@@ -0,0 +1,20 @@
1
+ module OpenAssets
2
+
3
+ module MarkerOutput
4
+
5
+ # whether this output is marker output for open assets.
6
+ def open_assets_marker?
7
+ return false unless script_pubkey.op_return?
8
+ !oa_payload.nil?
9
+ end
10
+
11
+ # get open asset payload.
12
+ # @return [OpenAssets::Payload] open asset payload.
13
+ def oa_payload
14
+ return nil unless script_pubkey.op_return?
15
+ Payload.parse_from_payload(script_pubkey.op_return_data)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAssets
4
+
5
+ MARKER = "\x4f\x41"
6
+ VERSION = "\x01\x00"
7
+
8
+ # the open assets payload
9
+ class Payload
10
+
11
+ attr_accessor :quantities
12
+ attr_accessor :metadata
13
+
14
+ def initialize(quantities = [], metadata = '')
15
+ @quantities = quantities
16
+ @metadata = metadata
17
+ end
18
+
19
+ # parse open assets payload
20
+ # @return [Payload] a open assets payload object, if payload is invalid, return nil.
21
+ def self.parse_from_payload(payload)
22
+ buf = StringIO.new(payload)
23
+ marker = buf.read(2)
24
+ version = buf.read(2)
25
+ return nil if marker != MARKER || version != VERSION
26
+ count = Tapyrus.unpack_var_int_from_io(buf)
27
+ return nil unless count
28
+ quantities = []
29
+ count.times do
30
+ quantities << LEB128.decode_unsigned(buf, buf.pos)
31
+ end
32
+ metadata_length = Tapyrus.unpack_var_int_from_io(buf)
33
+ return nil if metadata_length.nil? || buf.length < metadata_length + buf.pos
34
+ metadata = buf.read(metadata_length).each_byte.map(&:chr).join
35
+ new(quantities, metadata)
36
+ rescue
37
+ # LEB128#decode_unsigned raise 'undefined method `unpack' for nil:NilClass'
38
+ # for invalid format such as "018f8f" (the most significant bit of the last byte should be 0)
39
+ nil
40
+ end
41
+
42
+ # generate binary payload
43
+ def to_payload
44
+ payload = String.new
45
+ payload << MARKER
46
+ payload << VERSION
47
+ payload << Tapyrus.pack_var_int(quantities.size) << quantities.map{|q| LEB128.encode_unsigned(q).read }.join
48
+ payload << Tapyrus.pack_var_int(metadata.length) << metadata.bytes.map{|b| sprintf("%02x", b)}.join.htb
49
+ payload
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAssets
4
+ module Util
5
+ class << self
6
+ OA_VERSION_BYTE = '17' # 0x23
7
+ OA_VERSION_BYTE_TESTNET = '73' # 0x115
8
+
9
+ def script_to_asset_id(script)
10
+ hash_to_asset_id(Tapyrus.hash160(script))
11
+ end
12
+
13
+ private
14
+
15
+ def hash_to_asset_id(hash)
16
+ hash = oa_version_byte + hash
17
+ Tapyrus::Base58.encode(hash + Tapyrus.calc_checksum(hash))
18
+ end
19
+
20
+ def oa_version_byte
21
+ case Tapyrus.chain_params.network
22
+ when 'mainnet' then OA_VERSION_BYTE
23
+ when 'testnet', 'regtest' then OA_VERSION_BYTE_TESTNET
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/openassets.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'leb128'
2
+
3
+ module OpenAssets
4
+
5
+ autoload :MarkerOutput, 'openassets/marker_output'
6
+ autoload :Payload, 'openassets/payload'
7
+ autoload :Util, 'openassets/util'
8
+
9
+ end
@@ -0,0 +1,38 @@
1
+ module Tapyrus
2
+
3
+ # Base58Check encoding
4
+ # https://en.bitcoin.it/wiki/Base58Check_encoding
5
+ module Base58
6
+ module_function
7
+
8
+ ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
9
+ SIZE = ALPHABET.size
10
+
11
+ # encode hex value to base58 string.
12
+ def encode(hex)
13
+ leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
14
+ int_val = hex.to_i(16)
15
+ base58_val = ''
16
+ while int_val > 0
17
+ int_val, remainder = int_val.divmod(SIZE)
18
+ base58_val = ALPHABET[remainder] + base58_val
19
+ end
20
+ ('1' * leading_zero_bytes) + base58_val
21
+ end
22
+
23
+ # decode base58 string to hex value.
24
+ def decode(base58_val)
25
+ int_val = 0
26
+ base58_val.reverse.split(//).each_with_index do |char,index|
27
+ raise ArgumentError, 'Value passed not a valid Base58 String.' if (char_index = ALPHABET.index(char)).nil?
28
+ int_val += char_index * (SIZE ** index)
29
+ end
30
+ s = int_val.to_even_length_hex
31
+ s = '' if s == '00'
32
+ leading_zero_bytes = (base58_val.match(/^([1]+)/) ? $1 : '').size
33
+ s = ('00' * leading_zero_bytes) + s if leading_zero_bytes > 0
34
+ s
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,77 @@
1
+ module Tapyrus
2
+ class Block
3
+
4
+ attr_accessor :header
5
+ attr_accessor :transactions
6
+
7
+ def initialize(header, transactions = [])
8
+ @header = header
9
+ @transactions = transactions
10
+ end
11
+
12
+ def self.parse_from_payload(payload)
13
+ Tapyrus::Message::Block.parse_from_payload(payload).to_block
14
+ end
15
+
16
+ def hash
17
+ header.hash
18
+ end
19
+
20
+ def block_hash
21
+ header.block_hash
22
+ end
23
+
24
+ # calculate block weight
25
+ def weight
26
+ stripped_size * (WITNESS_SCALE_FACTOR - 1) + size
27
+ end
28
+
29
+ # calculate total size (include witness data.)
30
+ def size
31
+ 80 + Tapyrus.pack_var_int(transactions.size).bytesize +
32
+ transactions.inject(0){|sum, tx| sum + (tx.witness? ? tx.serialize_witness_format.bytesize : tx.serialize_old_format.bytesize)}
33
+ end
34
+
35
+ # calculate base size (not include witness data.)
36
+ def stripped_size
37
+ 80 + Tapyrus.pack_var_int(transactions.size).bytesize +
38
+ transactions.inject(0){|sum, tx| sum + tx.serialize_old_format.bytesize}
39
+ end
40
+
41
+ # check the merkle root in the block header matches merkle root calculated from tx list.
42
+ def valid_merkle_root?
43
+ calculate_merkle_root == header.merkle_root
44
+ end
45
+
46
+ # calculate merkle root from tx list.
47
+ def calculate_merkle_root
48
+ Tapyrus::MerkleTree.build_from_leaf(transactions.map(&:tx_hash)).merkle_root
49
+ end
50
+
51
+ # check the witness commitment in coinbase tx matches witness commitment calculated from tx list.
52
+ def valid_witness_commitment?
53
+ transactions[0].witness_commitment == calculate_witness_commitment
54
+ end
55
+
56
+ # calculate witness commitment from tx list.
57
+ def calculate_witness_commitment
58
+ witness_hashes = [COINBASE_WTXID]
59
+ witness_hashes += (transactions[1..-1].map(&:witness_hash))
60
+ reserved_value = transactions[0].inputs[0].script_witness.stack.map(&:bth).join
61
+ root_hash = Tapyrus::MerkleTree.build_from_leaf(witness_hashes).merkle_root
62
+ Tapyrus.double_sha256([root_hash + reserved_value].pack('H*')).bth
63
+ end
64
+
65
+ # return this block height. block height is included in coinbase.
66
+ # if block version under 1, height does not include in coinbase, so return nil.
67
+ def height
68
+ return nil if header.version < 2
69
+ coinbase_tx = transactions[0]
70
+ return nil unless coinbase_tx.coinbase_tx?
71
+ buf = StringIO.new(coinbase_tx.inputs[0].script_sig.to_payload)
72
+ len = Tapyrus.unpack_var_int_from_io(buf)
73
+ buf.read(len).reverse.bth.to_i(16)
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,88 @@
1
+ module Tapyrus
2
+
3
+ # Block Header
4
+ class BlockHeader
5
+
6
+ attr_accessor :version
7
+ attr_accessor :prev_hash
8
+ attr_accessor :merkle_root
9
+ attr_accessor :time # unix timestamp
10
+ attr_accessor :bits
11
+ attr_accessor :nonce
12
+
13
+ def initialize(version, prev_hash, merkle_root, time, bits, nonce)
14
+ @version = version
15
+ @prev_hash = prev_hash
16
+ @merkle_root = merkle_root
17
+ @time = time
18
+ @bits = bits
19
+ @nonce = nonce
20
+ end
21
+
22
+ def self.parse_from_payload(payload)
23
+ version, prev_hash, merkle_root, time, bits, nonce = payload.unpack('Va32a32VVV')
24
+ new(version, prev_hash.bth, merkle_root.bth, time, bits, nonce)
25
+ end
26
+
27
+ def to_payload
28
+ [version, prev_hash.htb, merkle_root.htb, time, bits, nonce].pack('Va32a32VVV')
29
+ end
30
+
31
+ # compute difficulty target from bits.
32
+ def difficulty_target
33
+ exponent = ((bits >> 24) & 0xff)
34
+ mantissa = bits & 0x7fffff
35
+ mantissa *= -1 if (bits & 0x800000) > 0
36
+ (mantissa * 2 ** (8 * (exponent - 3)))
37
+ end
38
+
39
+ def hash
40
+ calc_hash.to_i(16)
41
+ end
42
+
43
+ def block_hash
44
+ calc_hash
45
+ end
46
+
47
+ # block hash(big endian)
48
+ def block_id
49
+ block_hash.rhex
50
+ end
51
+
52
+ # evaluate block header
53
+ def valid?
54
+ valid_pow? && valid_timestamp?
55
+ end
56
+
57
+ # evaluate valid proof of work.
58
+ def valid_pow?
59
+ block_id.hex < difficulty_target
60
+ end
61
+
62
+ # evaluate valid timestamp.
63
+ # https://en.bitcoin.it/wiki/Block_timestamp
64
+ def valid_timestamp?
65
+ time <= Time.now.to_i + Tapyrus::MAX_FUTURE_BLOCK_TIME
66
+ end
67
+
68
+ # compute chain work of this block.
69
+ # @return [Integer] a chain work.
70
+ def work
71
+ target = difficulty_target
72
+ return 0 if target < 1
73
+ 115792089237316195423570985008687907853269984665640564039457584007913129639936.div(target + 1) # 115792089237316195423570985008687907853269984665640564039457584007913129639936 is 2**256
74
+ end
75
+
76
+ def ==(other)
77
+ other && other.to_payload == to_payload
78
+ end
79
+
80
+ private
81
+
82
+ def calc_hash
83
+ Tapyrus.double_sha256(to_payload).bth
84
+ end
85
+
86
+ end
87
+
88
+ end