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 +4 -4
- data/README.md +14 -0
- data/lib/generators/glueby/contract/templates/timestamp_table.rb.erb +4 -1
- data/lib/glueby/configuration.rb +6 -0
- data/lib/glueby/contract/active_record/timestamp.rb +8 -1
- data/lib/glueby/contract/errors.rb +1 -0
- data/lib/glueby/contract/fee_estimator.rb +5 -1
- data/lib/glueby/contract/timestamp.rb +51 -6
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +2 -0
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +11 -3
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +12 -4
- data/lib/glueby/internal/wallet.rb +4 -3
- data/lib/glueby/version.rb +1 -1
- data/lib/tasks/glueby/contract/timestamp.rake +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b053cde5755947020d018939a4efa0a042e830232aff3e4d2a4a4a9b53caa54
|
4
|
+
data.tar.gz: 5fcfb3f983b687f6942901d7f56c9f70a5123b97e0f5eb313d3a011632824f76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/glueby/configuration.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
# @
|
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
|
-
|
97
|
-
|
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
|
-
|
91
|
-
|
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
|
88
|
-
# - If label=:
|
89
|
-
def list_unspent(only_finalized = true, label =
|
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
|
|
data/lib/glueby/version.rb
CHANGED
@@ -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.
|
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
|
+
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: []
|