glueby 0.5.0 → 0.6.1

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: 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: []