glueby 0.5.0 → 0.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14bc1f60be9eefa4527231fb46fbb0d96b7a2253b1634d94b3a8464290d2ddbb
4
- data.tar.gz: b268217f39285ae42fc2a4107bfcb5c32d9a71225e1fbb2b01296d24e62f1a1f
3
+ metadata.gz: 2b053cde5755947020d018939a4efa0a042e830232aff3e4d2a4a4a9b53caa54
4
+ data.tar.gz: 5fcfb3f983b687f6942901d7f56c9f70a5123b97e0f5eb313d3a011632824f76
5
5
  SHA512:
6
- metadata.gz: 5a51e8f38bf391baec903a06e240294e8e75c5a881285f9be369009b77bf6fe9e8fe86fe41f43a1659344a6a38c1fcb3e2293951e8bb1a41d8beb282f63e96f6
7
- data.tar.gz: 464fb058d159a083ab096bdb077981b65069e60d1fb73d664d6ea7fb09555c2e0794f4266bb114b5d4d315910f884a3548e6dfd1cd3412c93395f3433a75eaad
6
+ metadata.gz: 440cd7203e5d411dc0aca3571e2eaa14b2c2ef85ca97d9ed60c7b9099d206dc9d4fbaa4dfb65190ddcc9fc71bbb57555abc42cde5cf2d3319fa4c8c18f3b70cf
7
+ data.tar.gz: 4dac9b8cb1a8a6670e8ee0458f467c66c91994b103e8d9513bbbfb926c27f9b0541de4bdfe12085edb58b1ac9f761775abf88f3dcb93ab43f9ba17ad0c96f840
data/README.md CHANGED
@@ -443,6 +443,20 @@ Configuration:
443
443
 
444
444
  ```
445
445
 
446
+ ## Other configurations
447
+
448
+ ### Default fixed fee for the FixedFeeEstimator
449
+
450
+ The architecture of Glueby accepts any fee estimation strategies for paying transactions fee. However, we officially support only one strategy: the fixed fee strategy.
451
+ It just returns a fixed fee value without any estimation.
452
+ Here provides a configuration to modify the default fixed fee value it returns like this:
453
+
454
+ ```ruby
455
+ Glueby.configure do |config|
456
+ config.default_fixed_fee = 10_000
457
+ end
458
+ ```
459
+
446
460
 
447
461
  ## Development
448
462
 
@@ -2,10 +2,13 @@ class CreateTimestamp < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  create_table :glueby_timestamps<%= table_options %> do |t|
4
4
  t.string :txid
5
- t.integer :status
5
+ t.integer :status, null: false, default: 0
6
6
  t.string :content_hash
7
7
  t.string :prefix
8
8
  t.string :wallet_id
9
+ t.integer :timestamp_type, null: false, default: 0
10
+ t.string :p2c_address
11
+ t.string :payment_base
9
12
  end
10
13
  end
11
14
  end
@@ -82,5 +82,11 @@ module Glueby
82
82
  def utxo_provider_config=(config)
83
83
  UtxoProvider.configure(config)
84
84
  end
85
+
86
+ # Set default fixed fee to the FixedFeeEstimator
87
+ # @param [Integer] fee The default fee value in tapyrus to the FixedFeeEstimator
88
+ def default_fixed_fee=(fee)
89
+ Contract::FixedFeeEstimator.default_fixed_fee = fee
90
+ end
85
91
  end
86
92
  end
@@ -4,15 +4,22 @@ module Glueby
4
4
  class Timestamp < ::ActiveRecord::Base
5
5
  include Glueby::Contract::Timestamp::Util
6
6
  enum status: { init: 0, unconfirmed: 1, confirmed: 2 }
7
+ enum timestamp_type: { simple: 0, trackable: 1 }
7
8
 
8
9
  # @param [Hash] attributes attributes which consist of:
9
10
  # - wallet_id
10
11
  # - content
11
12
  # - prefix(optional)
13
+ # - timestamp_type(optional)
12
14
  def initialize(attributes = nil)
13
15
  @content_hash = Tapyrus.sha256(attributes[:content]).bth
14
16
  super(wallet_id: attributes[:wallet_id], content_hash: @content_hash,
15
- prefix: attributes[:prefix] ? attributes[:prefix] : '', status: :init)
17
+ prefix: attributes[:prefix] ? attributes[:prefix] : '', status: :init, timestamp_type: attributes[:timestamp_type] || :simple)
18
+ end
19
+
20
+ # Return true if timestamp type is 'trackable' and output in timestamp transaction has not been spent yet, otherwise return false.
21
+ def latest
22
+ trackable?
16
23
  end
17
24
  end
18
25
  end
@@ -5,6 +5,7 @@ module Glueby
5
5
  class InsufficientTokens < StandardError; end
6
6
  class InvalidAmount < StandardError; end
7
7
  class InvalidTokenType < StandardError; end
8
+ class InvalidTimestampType < StandardError; end
8
9
  class TxAlreadyBroadcasted < StandardError; end
9
10
  class UnsupportedTokenType < StandardError; end
10
11
  class UnknownScriptPubkey < StandardError; end
@@ -22,7 +22,11 @@ module Glueby
22
22
  class FixedFeeEstimator
23
23
  include FeeEstimator
24
24
 
25
- def initialize(fixed_fee: 10_000)
25
+ class << self
26
+ attr_accessor :default_fixed_fee
27
+ end
28
+
29
+ def initialize(fixed_fee: FixedFeeEstimator.default_fixed_fee || 10_000)
26
30
  @fixed_fee = fixed_fee
27
31
  end
28
32
 
@@ -9,6 +9,8 @@ module Glueby
9
9
  # Storing timestamp transaction to the blockchain enables everyone to verify that the data existed at that time and a user signed it.
10
10
  class Timestamp
11
11
  include Glueby::Contract::TxBuilder
12
+
13
+ P2C_DEFAULT_VALUE = 1_000
12
14
 
13
15
  autoload :Syncer, 'glueby/contract/timestamp/syncer'
14
16
 
@@ -16,9 +18,29 @@ module Glueby
16
18
  include Glueby::Internal::Wallet::TapyrusCoreWalletAdapter::Util
17
19
  module_function
18
20
 
19
- def create_txs(wallet, prefix, data, fee_estimator, utxo_provider)
21
+ # @param [Glueby::Wallet] wallet
22
+ # @param [Array] data The data to be used for generating pay-to-contract address
23
+ # @return [Array(String, String)]
24
+ # Return (pay-to-contract address, public key used for generating address)
25
+ def create_pay_to_contract_address(wallet, contents: nil)
26
+ pubkey = wallet.internal_wallet.create_pubkey.pubkey
27
+ # Calculate P + H(P || contents)G
28
+ group = ECDSA::Group::Secp256k1
29
+ p = Tapyrus::Key.new(pubkey: pubkey).to_point # P
30
+ commitment = Tapyrus.sha256(p.to_hex(true).htb + contents.join).bth.to_i(16) % group.order # H(P || contents)
31
+ point = p + group.generator.multiply_by_scalar(commitment) # P + H(P || contents)G
32
+ [Tapyrus::Key.new(pubkey: point.to_hex(true)).to_p2pkh, pubkey] # [p2c address, P]
33
+ end
34
+
35
+ def create_txs(wallet, prefix, data, fee_estimator, utxo_provider, type: :simple)
20
36
  txb = Tapyrus::TxBuilder.new
21
- txb.data(prefix + data)
37
+ if type == :simple
38
+ txb.data(prefix + data)
39
+ elsif type == :trackable
40
+ p2c_address, payment_base = create_pay_to_contract_address(wallet, contents: [prefix, data])
41
+ txb.pay(p2c_address, P2C_DEFAULT_VALUE)
42
+ end
43
+
22
44
  fee = fee_estimator.fee(dummy_tx(txb.build))
23
45
  if utxo_provider
24
46
  script_pubkey = Tapyrus::Script.parse_from_addr(wallet.internal_wallet.receive_address)
@@ -41,8 +63,20 @@ module Glueby
41
63
  end
42
64
  end
43
65
 
66
+ prev_txs = if funding_tx
67
+ output = funding_tx.outputs.first
68
+ [{
69
+ txid: funding_tx.txid,
70
+ vout: 0,
71
+ scriptPubKey: output.script_pubkey.to_hex,
72
+ amount: output.value
73
+ }]
74
+ else
75
+ []
76
+ end
77
+
44
78
  txb.fee(fee).change_address(wallet.internal_wallet.change_address)
45
- [funding_tx, wallet.internal_wallet.sign_tx(txb.build)]
79
+ [funding_tx, wallet.internal_wallet.sign_tx(txb.build, prev_txs), p2c_address, payment_base]
46
80
  end
47
81
 
48
82
  def get_transaction(tx)
@@ -53,6 +87,9 @@ module Glueby
53
87
 
54
88
  attr_reader :tx, :txid
55
89
 
90
+ # p2c_address and payment_base is used in `trackable` type
91
+ attr_reader :p2c_address, :payment_base
92
+
56
93
  # @param [String] content Data to be hashed and stored in blockchain.
57
94
  # @param [String] prefix prefix of op_return data
58
95
  # @param [Glueby::Contract::FeeEstimator] fee_estimator
@@ -60,21 +97,29 @@ module Glueby
60
97
  # - :sha256
61
98
  # - :double_sha256
62
99
  # - :none
63
- # @raise [Glueby::Contract::Errors::UnsupportedDigestType] if digest unsupport
100
+ # @param [Symbol] timestamp_type
101
+ # - :simple
102
+ # - :trackable
103
+ # @raise [Glueby::Contract::Errors::UnsupportedDigestType] if digest is unsupported
104
+ # @raise [Glueby::Contract::Errors::InvalidTimestampType] if timestamp_type is unsupported
64
105
  def initialize(
65
106
  wallet:,
66
107
  content:,
67
108
  prefix: '',
68
109
  fee_estimator: Glueby::Contract::FixedFeeEstimator.new,
69
110
  digest: :sha256,
70
- utxo_provider: nil
111
+ utxo_provider: nil,
112
+ timestamp_type: :simple
71
113
  )
72
114
  @wallet = wallet
73
115
  @content = content
74
116
  @prefix = prefix
75
117
  @fee_estimator = fee_estimator
118
+ raise Glueby::Contract::Errors::UnsupportedDigestType, "#{digest} is invalid digest, supported digest are :sha256, :double_sha256, and :none." unless [:sha256, :double_sha256, :none].include?(digest)
76
119
  @digest = digest
77
120
  @utxo_provider = utxo_provider
121
+ raise Glueby::Contract::Errors::InvalidTimestampType, "#{timestamp_type} is invalid type, supported types are :simple, and :trackable." unless [:simple, :trackable].include?(timestamp_type)
122
+ @timestamp_type = timestamp_type
78
123
  end
79
124
 
80
125
  # broadcast to Tapyrus Core
@@ -84,7 +129,7 @@ module Glueby
84
129
  def save!
85
130
  raise Glueby::Contract::Errors::TxAlreadyBroadcasted if @txid
86
131
 
87
- funding_tx, @tx = create_txs(@wallet, @prefix, digest_content, @fee_estimator, @utxo_provider)
132
+ funding_tx, @tx, @p2c_address, @payment_base = create_txs(@wallet, @prefix, digest_content, @fee_estimator, @utxo_provider, type: @timestamp_type)
88
133
  @wallet.internal_wallet.broadcast(funding_tx) if funding_tx
89
134
  @txid = @wallet.internal_wallet.broadcast(@tx)
90
135
  end
@@ -72,6 +72,8 @@ module Glueby
72
72
  # @param [Boolean] only_finalized - The UTXOs includes only finalized UTXO value if it
73
73
  # is true. Default is true.
74
74
  # @param [String] label - Label for filtering UTXOs
75
+ # - If label is nil or :unlabeled, only unlabeled UTXOs will be returned.
76
+ # - If label=:all, it will return all utxos
75
77
  # @return [Array of UTXO]
76
78
  #
77
79
  # ## The UTXO structure
@@ -93,8 +93,15 @@ module Glueby
93
93
  wallet = AR::Wallet.find_by(wallet_id: wallet_id)
94
94
  utxos = wallet.utxos
95
95
  utxos = utxos.where(status: :finalized) if only_finalized
96
- utxos = utxos.where(label: label) if label && (label != :unlabeled)
97
- utxos = utxos.where(label: nil) if label == :unlabeled
96
+
97
+ if [:unlabeled, nil].include?(label)
98
+ utxos = utxos.where(label: nil)
99
+ elsif label && (label != :all)
100
+ utxos = utxos.where(label: label)
101
+ else
102
+ utxos
103
+ end
104
+
98
105
  utxos.map do |utxo|
99
106
  {
100
107
  txid: utxo.txid,
@@ -102,7 +109,8 @@ module Glueby
102
109
  script_pubkey: utxo.script_pubkey,
103
110
  color_id: utxo.color_id,
104
111
  amount: utxo.value,
105
- finalized: utxo.status == 'finalized'
112
+ finalized: utxo.status == 'finalized',
113
+ label: utxo.label
106
114
  }
107
115
  end
108
116
  end
@@ -82,14 +82,21 @@ module Glueby
82
82
  end
83
83
  end
84
84
 
85
+ # If label=nil, it will return unlabeled utxos to protect labeled utxos for specific purpose
86
+ # If label=:all, it will return all utxos
85
87
  def list_unspent(wallet_id, only_finalized = true, label = nil)
86
88
  perform_as(wallet_id) do |client|
87
89
  min_conf = only_finalized ? 1 : 0
88
90
  res = client.listunspent(min_conf)
89
91
 
90
- res = res.filter { |i| i['label'] == label } if label && (label != :unlabeled)
91
- res = res.filter { |i| i['label'] == "" } if label == :unlabeled
92
-
92
+ if [:unlabeled, nil].include?(label)
93
+ res = res.filter { |i| i['label'] == "" }
94
+ elsif label && (label != :all)
95
+ res = res.filter { |i| i['label'] == label }
96
+ else
97
+ res
98
+ end
99
+
93
100
  res.map do |i|
94
101
  script = Tapyrus::Script.parse_from_payload(i['scriptPubKey'].htb)
95
102
  color_id = if script.cp2pkh? || script.cp2sh?
@@ -101,7 +108,8 @@ module Glueby
101
108
  script_pubkey: i['scriptPubKey'],
102
109
  color_id: color_id,
103
110
  amount: tpc_to_tapyrus(i['amount']),
104
- finalized: i['confirmations'] != 0
111
+ finalized: i['confirmations'] != 0,
112
+ label: i['label']
105
113
  }
106
114
  end
107
115
  end
@@ -84,9 +84,10 @@ module Glueby
84
84
 
85
85
  # @param only_finalized [Boolean] The flag to get a UTXO with status only finalized
86
86
  # @param label [String] This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.
87
- # - If label is not specified (label=nil), all UTXOs will be returned.
88
- # - If label=:unlabeled, only unlabeled UTXOs will be returned.
89
- def list_unspent(only_finalized = true, label = nil)
87
+ # - If label is nil or :unlabeled, only unlabeled UTXOs will be returned.
88
+ # - If label=:all, all UTXOs will be returned.
89
+ def list_unspent(only_finalized = true, label = :unlabeled)
90
+ label = :unlabeled unless label
90
91
  wallet_adapter.list_unspent(id, only_finalized, label)
91
92
  end
92
93
 
@@ -1,3 +1,3 @@
1
1
  module Glueby
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.1"
3
3
  end
@@ -12,7 +12,7 @@ module Glueby
12
12
  timestamps.each do |t|
13
13
  begin
14
14
  wallet = Glueby::Wallet.load(t.wallet_id)
15
- funding_tx, tx = create_txs(wallet, t.prefix, t.content_hash, Glueby::Contract::FixedFeeEstimator.new, utxo_provider)
15
+ funding_tx, tx, p2c_address, payment_base = create_txs(wallet, t.prefix, t.content_hash, Glueby::Contract::FixedFeeEstimator.new, utxo_provider, type: t.timestamp_type.to_sym)
16
16
  if funding_tx
17
17
  ::ActiveRecord::Base.transaction do
18
18
  wallet.internal_wallet.broadcast(funding_tx)
@@ -21,7 +21,7 @@ module Glueby
21
21
  end
22
22
  ::ActiveRecord::Base.transaction do
23
23
  wallet.internal_wallet.broadcast(tx) do |tx|
24
- t.update(txid: tx.txid, status: :unconfirmed)
24
+ t.update(txid: tx.txid, status: :unconfirmed, p2c_address: p2c_address, payment_base: payment_base)
25
25
  end
26
26
  puts "timestamp tx was broadcasted (id=#{t.id}, txid=#{tx.txid})"
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glueby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-22 00:00:00.000000000 Z
11
+ date: 2021-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tapyrus
@@ -147,7 +147,7 @@ metadata:
147
147
  homepage_uri: https://github.com/chaintope/glueby
148
148
  source_code_uri: https://github.com/chaintope/glueby
149
149
  changelog_uri: https://github.com/chaintope/glueby
150
- post_install_message:
150
+ post_install_message:
151
151
  rdoc_options: []
152
152
  require_paths:
153
153
  - lib
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  version: '0'
164
164
  requirements: []
165
165
  rubygems_version: 3.2.3
166
- signing_key:
166
+ signing_key:
167
167
  specification_version: 4
168
168
  summary: A Ruby library of smart contracts that can be used on Tapyrus.
169
169
  test_files: []