osbc 0.1.5
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 +7 -0
- data/.env +5 -0
- data/.rspec +1 -0
- data/.rubocop.yml +273 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Dockerfile +17 -0
- data/Gemfile +109 -0
- data/Gemfile.lock +343 -0
- data/LICENSE.md +21 -0
- data/LICENSE.txt +21 -0
- data/Procfile +3 -0
- data/Procfile.dev +2 -0
- data/README.md +185 -0
- data/Rakefile +6 -0
- data/app/assets/builds/.keep +0 -0
- data/app/assets/config/manifest.js +5 -0
- data/app/assets/images/.keep +0 -0
- data/app/assets/images/bg.png +0 -0
- data/app/assets/images/gimage.png +0 -0
- data/app/assets/images/image.png +0 -0
- data/app/assets/images/logo.png +0 -0
- data/app/assets/images/outerspc.jpg +0 -0
- data/app/assets/images/proxy.jpg +0 -0
- data/app/assets/images/space.jpg +0 -0
- data/app/assets/images/space_four.jpg +0 -0
- data/app/assets/images/space_t.jpg +0 -0
- data/app/assets/images/space_th.jpg +0 -0
- data/app/assets/images/space_two.jpg +0 -0
- data/app/assets/images/th.jpg +0 -0
- data/app/assets/stylesheets/application.css +344 -0
- data/app/assets/stylesheets/application.tailwind.css +13 -0
- data/app/assets/stylesheets/home.css +0 -0
- data/app/channels/application_cable/channel.rb +6 -0
- data/app/channels/application_cable/connection.rb +6 -0
- data/app/controllers/api/v1/block_confirmations_controller.rb +65 -0
- data/app/controllers/application_controller.rb +72 -0
- data/app/controllers/blocks_controller.rb +20 -0
- data/app/controllers/chains_controller.rb +72 -0
- data/app/controllers/concerns/.keep +0 -0
- data/app/controllers/contracts_controller.rb +25 -0
- data/app/controllers/pools_controller.rb +73 -0
- data/app/controllers/signatures_controller.rb +25 -0
- data/app/controllers/tickets_controller.rb +76 -0
- data/app/controllers/transactions_controller.rb +48 -0
- data/app/controllers/users/confirmations_controller.rb +30 -0
- data/app/controllers/users/omniauth_callbacks_controller.rb +30 -0
- data/app/controllers/users/passwords_controller.rb +34 -0
- data/app/controllers/users/registrations_controller.rb +61 -0
- data/app/controllers/users/sessions_controller.rb +27 -0
- data/app/controllers/users/unlocks_controller.rb +30 -0
- data/app/controllers/wallets_controller.rb +18 -0
- data/app/helpers/application_helper.rb +4 -0
- data/app/helpers/blocks_helper.rb +4 -0
- data/app/helpers/chains_helper.rb +4 -0
- data/app/helpers/contracts_helper.rb +4 -0
- data/app/helpers/pools_helper.rb +4 -0
- data/app/helpers/signatures_helper.rb +4 -0
- data/app/helpers/tickets_helper.rb +4 -0
- data/app/helpers/transactions_helper.rb +4 -0
- data/app/helpers/wallets_helper.rb +4 -0
- data/app/javascript/application.js +3 -0
- data/app/javascript/controllers/application.js +9 -0
- data/app/javascript/controllers/hello_controller.js +7 -0
- data/app/javascript/controllers/index.js +11 -0
- data/app/jobs/application_job.rb +9 -0
- data/app/mailers/application_mailer.rb +6 -0
- data/app/models/acceptable_number_sequence.rb +4 -0
- data/app/models/acceptable_symbol_sequence.rb +4 -0
- data/app/models/acceptable_word.rb +4 -0
- data/app/models/application_record.rb +5 -0
- data/app/models/block.rb +17 -0
- data/app/models/chain.rb +10 -0
- data/app/models/concerns/.keep +0 -0
- data/app/models/concerns/sequences_validator.rb +30 -0
- data/app/models/concerns/wallet_exists_validator.rb +13 -0
- data/app/models/contract.rb +7 -0
- data/app/models/pool.rb +5 -0
- data/app/models/signature.rb +12 -0
- data/app/models/ticket.rb +11 -0
- data/app/models/transaction.rb +25 -0
- data/app/models/user.rb +44 -0
- data/app/models/wallet.rb +33 -0
- data/app/services/application_service.rb +23 -0
- data/app/services/assign_contracts_service.rb +162 -0
- data/app/services/create_ticket_service.rb +87 -0
- data/app/services/create_wallet_service.rb +20 -0
- data/app/services/transaction_to_block_service.rb +62 -0
- data/app/views/application/_featured_board.html.erb +77 -0
- data/app/views/application/home.html.slim +1 -0
- data/app/views/application/mining_profile.html.slim +59 -0
- data/app/views/application/privacy_policy.html.erb +0 -0
- data/app/views/application/terms.html.erb +0 -0
- data/app/views/blocks/_block.html.slim +13 -0
- data/app/views/blocks/_block.json.jbuilder +4 -0
- data/app/views/blocks/_form.html.slim +26 -0
- data/app/views/blocks/edit.html.slim +10 -0
- data/app/views/blocks/index.html.slim +12 -0
- data/app/views/blocks/index.json.jbuilder +3 -0
- data/app/views/blocks/new.html.slim +8 -0
- data/app/views/blocks/show.html.slim +8 -0
- data/app/views/blocks/show.json.jbuilder +3 -0
- data/app/views/chains/_chain.html.slim +16 -0
- data/app/views/chains/_chain.json.jbuilder +4 -0
- data/app/views/chains/_form.html.slim +30 -0
- data/app/views/chains/edit.html.slim +10 -0
- data/app/views/chains/index.html.slim +11 -0
- data/app/views/chains/index.json.jbuilder +3 -0
- data/app/views/chains/new.html.slim +8 -0
- data/app/views/chains/show.html.slim +10 -0
- data/app/views/chains/show.json.jbuilder +3 -0
- data/app/views/contracts/_contract.html.slim +8 -0
- data/app/views/contracts/_contract.json.jbuilder +4 -0
- data/app/views/contracts/_form.html.slim +34 -0
- data/app/views/contracts/edit.html.slim +10 -0
- data/app/views/contracts/index.html.slim +12 -0
- data/app/views/contracts/index.json.jbuilder +3 -0
- data/app/views/contracts/new.html.slim +8 -0
- data/app/views/contracts/show.html.slim +8 -0
- data/app/views/contracts/show.json.jbuilder +3 -0
- data/app/views/layouts/_alert.html.slim +6 -0
- data/app/views/layouts/_navbar.html.slim +27 -0
- data/app/views/layouts/_notice.html.slim +6 -0
- data/app/views/layouts/application.html.erb +32 -0
- data/app/views/layouts/mailer.html.erb +13 -0
- data/app/views/layouts/mailer.text.erb +1 -0
- data/app/views/pools/_form.html.slim +30 -0
- data/app/views/pools/_pool.html.slim +16 -0
- data/app/views/pools/_pool.json.jbuilder +4 -0
- data/app/views/pools/edit.html.slim +10 -0
- data/app/views/pools/index.html.slim +12 -0
- data/app/views/pools/index.json.jbuilder +3 -0
- data/app/views/pools/new.html.slim +8 -0
- data/app/views/pools/show.html.slim +8 -0
- data/app/views/pools/show.json.jbuilder +3 -0
- data/app/views/signatures/_form.html.slim +46 -0
- data/app/views/signatures/_signature.html.slim +28 -0
- data/app/views/signatures/_signature.json.jbuilder +4 -0
- data/app/views/signatures/edit.html.slim +10 -0
- data/app/views/signatures/index.html.slim +10 -0
- data/app/views/signatures/index.json.jbuilder +3 -0
- data/app/views/signatures/new.html.slim +8 -0
- data/app/views/signatures/show.html.slim +10 -0
- data/app/views/signatures/show.json.jbuilder +3 -0
- data/app/views/tickets/_form.html.slim +26 -0
- data/app/views/tickets/_ticket.html.slim +10 -0
- data/app/views/tickets/_ticket.json.jbuilder +4 -0
- data/app/views/tickets/edit.html.slim +10 -0
- data/app/views/tickets/index.html.slim +16 -0
- data/app/views/tickets/index.json.jbuilder +3 -0
- data/app/views/tickets/new.html.slim +10 -0
- data/app/views/tickets/show.html.slim +8 -0
- data/app/views/tickets/show.json.jbuilder +3 -0
- data/app/views/transactions/_form.html.slim +16 -0
- data/app/views/transactions/_transaction.html.slim +24 -0
- data/app/views/transactions/_transaction.json.jbuilder +4 -0
- data/app/views/transactions/edit.html.slim +10 -0
- data/app/views/transactions/index.html.slim +19 -0
- data/app/views/transactions/index.json.jbuilder +3 -0
- data/app/views/transactions/new.html.slim +9 -0
- data/app/views/transactions/show.html.slim +8 -0
- data/app/views/transactions/show.json.jbuilder +3 -0
- data/app/views/users/confirmations/new.html.erb +16 -0
- data/app/views/users/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/users/mailer/email_changed.html.erb +7 -0
- data/app/views/users/mailer/password_change.html.erb +3 -0
- data/app/views/users/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/users/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/users/passwords/edit.html.erb +25 -0
- data/app/views/users/passwords/new.html.erb +16 -0
- data/app/views/users/registrations/edit.html.erb +43 -0
- data/app/views/users/registrations/new.html.erb +37 -0
- data/app/views/users/sessions/new.html.erb +30 -0
- data/app/views/users/shared/_error_messages.html.erb +15 -0
- data/app/views/users/shared/_links.html.erb +25 -0
- data/app/views/users/unlocks/new.html.erb +16 -0
- data/app/views/wallets/_form.html.slim +30 -0
- data/app/views/wallets/_wallet.html.slim +13 -0
- data/app/views/wallets/_wallet.json.jbuilder +4 -0
- data/app/views/wallets/edit.html.slim +10 -0
- data/app/views/wallets/index.html.slim +18 -0
- data/app/views/wallets/index.json.jbuilder +3 -0
- data/app/views/wallets/new.html.slim +8 -0
- data/app/views/wallets/show.html.slim +11 -0
- data/app/views/wallets/show.json.jbuilder +3 -0
- data/app/workers/application_worker.rb +82 -0
- data/app/workers/assign_contract_worker.rb +27 -0
- data/app/workers/create_ticket_worker.rb +23 -0
- data/app/workers/create_wallet_worker.rb +21 -0
- data/app/workers/transaction_to_block_worker.rb +48 -0
- data/bin/bundle +114 -0
- data/bin/console +15 -0
- data/bin/dev +9 -0
- data/bin/importmap +5 -0
- data/bin/osbc +77 -0
- data/bin/rails +6 -0
- data/bin/rake +6 -0
- data/bin/setup +35 -0
- data/config/application.rb +25 -0
- data/config/boot.rb +6 -0
- data/config/cable.yml +10 -0
- data/config/credentials.yml.enc +1 -0
- data/config/database.yml +21 -0
- data/config/environment.rb +7 -0
- data/config/environments/development.rb +73 -0
- data/config/environments/production.rb +95 -0
- data/config/environments/test.rb +62 -0
- data/config/importmap.rb +9 -0
- data/config/initializers/assets.rb +14 -0
- data/config/initializers/content_security_policy.rb +26 -0
- data/config/initializers/devise.rb +311 -0
- data/config/initializers/filter_parameter_logging.rb +10 -0
- data/config/initializers/inflections.rb +17 -0
- data/config/initializers/permissions_policy.rb +12 -0
- data/config/locales/devise.en.yml +65 -0
- data/config/locales/en.yml +33 -0
- data/config/puma.rb +45 -0
- data/config/routes/api.rb +9 -0
- data/config/routes.rb +30 -0
- data/config/sidekiq.yml +10 -0
- data/config/storage.yml +34 -0
- data/config/tailwind.config.js +23 -0
- data/config.ru +8 -0
- data/coverage/.last_run.json +5 -0
- data/coverage/.resultset.json +1853 -0
- data/coverage/.resultset.json.lock +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
- data/coverage/assets/0.12.3/application.css +1 -0
- data/coverage/assets/0.12.3/application.js +7 -0
- data/coverage/assets/0.12.3/colorbox/border.png +0 -0
- data/coverage/assets/0.12.3/colorbox/controls.png +0 -0
- data/coverage/assets/0.12.3/colorbox/loading.gif +0 -0
- data/coverage/assets/0.12.3/colorbox/loading_background.png +0 -0
- data/coverage/assets/0.12.3/favicon_green.png +0 -0
- data/coverage/assets/0.12.3/favicon_red.png +0 -0
- data/coverage/assets/0.12.3/favicon_yellow.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/assets/0.12.3/loading.gif +0 -0
- data/coverage/assets/0.12.3/magnify.png +0 -0
- data/coverage/index.html +20731 -0
- data/db/migrate/20221018053949_devise_create_users.rb +45 -0
- data/db/migrate/20221019002956_create_chains.rb +13 -0
- data/db/migrate/20221020112137_create_blocks.rb +12 -0
- data/db/migrate/20221020123102_add_chain_to_blocks.rb +5 -0
- data/db/migrate/20221020150504_create_wallets.rb +13 -0
- data/db/migrate/20221022221059_create_transactions.rb +20 -0
- data/db/migrate/20221023011005_add_block_to_transactions.rb +5 -0
- data/db/migrate/20221023014707_create_contracts.rb +11 -0
- data/db/migrate/20221023040749_create_pools.rb +13 -0
- data/db/migrate/20221023041015_create_tickets.rb +11 -0
- data/db/migrate/20221023103509_add_contracts_count_to_block.rb +6 -0
- data/db/migrate/20221023110613_add_acceptable_word_list_to_users.rb +7 -0
- data/db/migrate/20221023113539_create_signatures.rb +19 -0
- data/db/migrate/20221023113750_create_acceptable_words.rb +9 -0
- data/db/migrate/20221023114152_create_acceptable_number_sequences.rb +9 -0
- data/db/migrate/20221023114203_create_acceptable_symbol_sequences.rb +9 -0
- data/db/migrate/20221023114324_add_user_acceptable_hash_to_tickets.rb +7 -0
- data/db/migrate/20221023114408_add_time_ref_to_tickets.rb +5 -0
- data/db/migrate/20221024125047_add_master_hash_to_blocks.rb +5 -0
- data/db/migrate/20221109161845_add_transactions_count_to_blocks.rb +5 -0
- data/db/migrate/20221117135003_add_balance_to_chains.rb +5 -0
- data/db/migrate/20221117203417_add_transaction_id_list_to_tickets.rb +5 -0
- data/db/migrate/20221118080357_add_api_keys_to_users.rb +6 -0
- data/db/schema.rb +179 -0
- data/db/seeds.rb +134 -0
- data/docker-compose.yml +53 -0
- data/entrypoint.sh +8 -0
- data/lib/assets/.keep +0 -0
- data/lib/osbc/osbc.rb +9 -0
- data/lib/outerspace/blockchain/version.rb +7 -0
- data/lib/outerspace/blockchain.rb +10 -0
- data/lib/tasks/.keep +0 -0
- data/lib/tasks/compose.rake +92 -0
- data/lib/tasks/compose_db.rake +71 -0
- data/lib/tasks/compose_logs.rake +95 -0
- data/lib/tasks/compose_test.rake +62 -0
- data/log/.keep +0 -0
- data/mining_concept.ipynb +284 -0
- data/outerspace-blockchain.gemspec +50 -0
- data/public/404.html +67 -0
- data/public/422.html +67 -0
- data/public/500.html +66 -0
- data/public/apple-touch-icon-precomposed.png +0 -0
- data/public/apple-touch-icon.png +0 -0
- data/public/favicon.ico +0 -0
- data/public/robots.txt +1 -0
- data/storage/.keep +0 -0
- data/tmp/.keep +0 -0
- data/tmp/pids/.keep +0 -0
- data/tmp/storage/.keep +0 -0
- data/vendor/.keep +0 -0
- data/vendor/javascript/.keep +0 -0
- metadata +643 -0
data/app/models/user.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class User < ApplicationRecord
|
|
4
|
+
# Include default devise modules. Others available are:
|
|
5
|
+
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
|
6
|
+
after_create :create_wallet
|
|
7
|
+
devise :database_authenticatable, :registerable,
|
|
8
|
+
:recoverable, :rememberable, :validatable
|
|
9
|
+
|
|
10
|
+
has_one :wallet
|
|
11
|
+
has_many :tickets
|
|
12
|
+
validates :email, presence: true, uniqueness: true
|
|
13
|
+
validates :password, presence: true, length: { minimum: 6 }
|
|
14
|
+
validates :username, presence: true, uniqueness: true
|
|
15
|
+
before_create :save_acceptable_assets
|
|
16
|
+
before_create :save_api_keys
|
|
17
|
+
has_many :signatures
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
def create_wallet
|
|
21
|
+
CreateWalletWorker.perform_async(self.id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def save_acceptable_assets
|
|
25
|
+
words = AcceptableWord.all.sample(4)
|
|
26
|
+
number_sequences = AcceptableNumberSequence.all.sample(4)
|
|
27
|
+
symbol_sequences = AcceptableSymbolSequence.all.sample(4)
|
|
28
|
+
|
|
29
|
+
words_to_save = words.map { |word| word.word }
|
|
30
|
+
|
|
31
|
+
number_sequences_to_save = number_sequences.map { |number_sequence| number_sequence.seq }
|
|
32
|
+
|
|
33
|
+
symbol_sequences_to_save = symbol_sequences.map { |symbol_sequence| symbol_sequence.seq }
|
|
34
|
+
|
|
35
|
+
self.acceptable_words = words_to_save
|
|
36
|
+
self.acceptable_number_sequences = number_sequences_to_save
|
|
37
|
+
self.acceptable_symbol_sequences = symbol_sequences_to_save
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def save_api_keys
|
|
41
|
+
self.api_key = SecureRandom.hex(32)
|
|
42
|
+
self.api_secret = SecureRandom.hex(32)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Wallet < ApplicationRecord
|
|
4
|
+
belongs_to :user
|
|
5
|
+
|
|
6
|
+
validates :user_id, presence: true
|
|
7
|
+
validates :pr_key, presence: false
|
|
8
|
+
validates :pv_key, presence: false
|
|
9
|
+
# validates :balance, presence: true, numericality: { equal_to: 0.0 }, on: :create
|
|
10
|
+
validates :status, presence: true, inclusion: %w(active inactive)
|
|
11
|
+
|
|
12
|
+
before_create :create_keys
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
enum status: { active: 0, inactive: 1 }
|
|
16
|
+
|
|
17
|
+
def create_keys(pv_random = nil, pr_random = nil)
|
|
18
|
+
if pv_random.nil? && pr_random.nil?
|
|
19
|
+
pv_random = SecureRandom.hex(64)
|
|
20
|
+
pr_random = SecureRandom.hex(64)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
dig_pv = Digest::SHA256.hexdigest(pv_random)
|
|
24
|
+
dig_pr = Digest::SHA256.hexdigest(pr_random)
|
|
25
|
+
|
|
26
|
+
if Wallet.exists?(pr_key: dig_pr) || Wallet.exists?(pv_key: dig_pv)
|
|
27
|
+
raise "Key already exists"
|
|
28
|
+
else
|
|
29
|
+
self.pr_key = dig_pr
|
|
30
|
+
self.pv_key = dig_pv
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class ApplicationService
|
|
4
|
+
private
|
|
5
|
+
def dev_error(e)
|
|
6
|
+
if env_acceptable?
|
|
7
|
+
puts "#{e.class}: #{e.message}"
|
|
8
|
+
puts e.backtrace
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def user_exists?
|
|
13
|
+
User.find_by(id: user_id).present?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def wallet_exists?(method, key)
|
|
17
|
+
Wallet.find_by(method => key).present?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def env_acceptable?
|
|
21
|
+
Rails.env.development? || Rails.env.test?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AssignContractsService < ApplicationService
|
|
4
|
+
def initialize(contract_ids, ticket_id)
|
|
5
|
+
@contract_ids = contract_ids
|
|
6
|
+
@ticket_id = ticket_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call
|
|
10
|
+
assign_contract
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
attr_reader :contract_ids, :ticket_id
|
|
15
|
+
|
|
16
|
+
def ticket
|
|
17
|
+
@ticket ||= Ticket.find_by(id: ticket_id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def contracts
|
|
21
|
+
@contracts ||= Contract.where(id: contract_ids)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def block
|
|
25
|
+
@block ||= Block.where(master_hash: nil).last
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def block_confirmed?
|
|
29
|
+
block.nonce >= ENV["CONTRACTS_LIMIT"].to_i
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update_nonce
|
|
33
|
+
block.update(nonce: block.nonce + 1)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def signatures_limit_reached?(contract)
|
|
37
|
+
contract.signatures.count == ENV["SIGNATURES_LIMIT"].to_i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def create_block
|
|
41
|
+
Block.create!(chain: Chain.first, previous_hash: block.master_hash,
|
|
42
|
+
master_hash: nil, nonce: 0, connections: 0, contracts_count: 0,
|
|
43
|
+
contracts_limit: ENV["CONTRACTS_LIMIT"].to_i, block_data: "block #{block.id + 1}")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def confirm_block
|
|
47
|
+
return if confirmed_now == true
|
|
48
|
+
@confirmed_now = true
|
|
49
|
+
block.update(master_hash: generate_master_hash)
|
|
50
|
+
block.reload
|
|
51
|
+
@new_block = create_block
|
|
52
|
+
pay_receivers
|
|
53
|
+
pay_miners
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def complete_contracts
|
|
57
|
+
@complete_contracts ||= []
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def uncomplete_contracts
|
|
61
|
+
@uncomplete_contracts ||= []
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def signatures
|
|
65
|
+
@signatures ||= []
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def generate_master_hash
|
|
69
|
+
Digest::SHA256.hexdigest(complete_contracts.map(&:signatures).flatten.map(&:signature).join)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def complete_contracts_limit_reached?
|
|
73
|
+
complete_contracts.count == ENV["CONTRACTS_LIMIT"].to_i
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def confirmed_now
|
|
77
|
+
@confirmed_now ||= false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def pay_receivers
|
|
81
|
+
block_transactions = block.transactions
|
|
82
|
+
conts = block_transactions.map(&:contract)
|
|
83
|
+
conts_to_destroy = []
|
|
84
|
+
conts.each do |contract|
|
|
85
|
+
if contract.signatures.count < ENV["SIGNATURES_LIMIT"].to_i
|
|
86
|
+
transact = block_transactions.find_by(contract: contract)
|
|
87
|
+
conts_to_destroy << contract.id
|
|
88
|
+
transact.update(block: @new_block)
|
|
89
|
+
Contract.create(blk_transaction: transact)
|
|
90
|
+
end
|
|
91
|
+
amount = contract.blk_transaction.amount.to_f - contract.blk_transaction.fee.to_f
|
|
92
|
+
wallet = Wallet.find_by(pr_key: contract.blk_transaction.receiver_key)
|
|
93
|
+
wallet.update(balance: wallet.balance + amount)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
Contract.where(id: conts_to_destroy).destroy_all
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def payed_miners
|
|
100
|
+
@payed_miners ||= []
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def pay_miners
|
|
104
|
+
tickets = Ticket.where(pool_id: block.pool.id)
|
|
105
|
+
total_signatures = tickets.map(&:signatures).map(&:count).sum
|
|
106
|
+
counted_users = []
|
|
107
|
+
amount_to_pay = []
|
|
108
|
+
tickets.each do |ticket|
|
|
109
|
+
signatures = ticket.signatures
|
|
110
|
+
user = ticket.user
|
|
111
|
+
unless counted_users.include?(user)
|
|
112
|
+
counted_users << user
|
|
113
|
+
amount_to_pay << signatures.count
|
|
114
|
+
else
|
|
115
|
+
amount_to_pay[counted_users.index(user)] += signatures.count
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
amount_to_pay.each_with_index do |amount, index|
|
|
119
|
+
next if payed_miners.include?(counted_users[index])
|
|
120
|
+
wallet = counted_users[index].wallet
|
|
121
|
+
wallet.update(balance: wallet.balance + (amount.to_f / total_signatures.to_f) * block.pool.amount)
|
|
122
|
+
payed_miners << counted_users[index]
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def new_signature(contract)
|
|
127
|
+
contract.update(signatures_count: contract.signatures_count + 1)
|
|
128
|
+
Signature.new(contract_id: contract.id, signature: ticket.user_acceptable_hash, ticket_id: ticket.id, user_id: ticket.user_id)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def parse_in_arrays(contract)
|
|
132
|
+
uncomplete_contracts << contract unless signatures_limit_reached?(contract)
|
|
133
|
+
complete_contracts << contract if signatures_limit_reached?(contract)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def add_signature(contract)
|
|
137
|
+
return if signatures_limit_reached?(contract) || confirmed_now == true || block_confirmed?
|
|
138
|
+
signatures << new_signature(contract)
|
|
139
|
+
contract.update(status: (contract.status + 1))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def block_actions(contract)
|
|
143
|
+
update_nonce if signatures_limit_reached?(contract)
|
|
144
|
+
confirm_block if complete_contracts_limit_reached? || block_confirmed?
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def signatures_import(signatures)
|
|
148
|
+
Signature.import signatures if signatures.present?
|
|
149
|
+
ticket.update(status: :inactive)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def assign_contract
|
|
153
|
+
contracts.each do |contract|
|
|
154
|
+
parse_in_arrays(contract)
|
|
155
|
+
add_signature(contract)
|
|
156
|
+
end
|
|
157
|
+
signatures_import(signatures)
|
|
158
|
+
contracts.each do |contract|
|
|
159
|
+
block_actions(contract)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateTicketService < ApplicationService
|
|
4
|
+
def initialize(user_id, pool_id, time_ref)
|
|
5
|
+
@user_id = user_id
|
|
6
|
+
@pool_id = pool_id
|
|
7
|
+
@time_ref = time_ref
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
return false if ticket_exists?
|
|
12
|
+
return false unless user_exists?
|
|
13
|
+
if ticket_created?
|
|
14
|
+
update_block_connections
|
|
15
|
+
true
|
|
16
|
+
else
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
attr_reader :user_id, :pool_id, :time_ref
|
|
23
|
+
|
|
24
|
+
def block
|
|
25
|
+
@block ||= Block.where(master_hash: nil).last
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def transactions
|
|
29
|
+
@transactions ||= block.transactions.where(created_at: time_ref..Time.now)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def user
|
|
33
|
+
@user ||= User.find(user_id)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def word
|
|
37
|
+
@word ||= user.acceptable_words.sample
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def number_sequence
|
|
41
|
+
@number_sequence ||= user.acceptable_number_sequences.sample
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def symbol_sequence
|
|
45
|
+
@symbol_sequence ||= user.acceptable_symbol_sequences.sample
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def generate_transaction_id_list
|
|
49
|
+
transactions.map(&:id)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def shuffled_string
|
|
53
|
+
puts "Word: #{word}"
|
|
54
|
+
puts "Number sequence: #{number_sequence}"
|
|
55
|
+
puts "Symbol sequence: #{symbol_sequence}"
|
|
56
|
+
string_sum = (word + number_sequence + symbol_sequence).split("").shuffle.join
|
|
57
|
+
puts "Shuffled string: #{string_sum}"
|
|
58
|
+
string_sum
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def generate_user_acceptable_hash
|
|
62
|
+
hash = Digest::SHA256.hexdigest(shuffled_string)
|
|
63
|
+
puts "Hash: #{hash}"
|
|
64
|
+
block_hash = Digest::SHA256.hexdigest(@transactions.to_json)
|
|
65
|
+
puts "Block hash: #{block_hash}"
|
|
66
|
+
master_hash = Digest::SHA256.hexdigest(hash + block_hash)
|
|
67
|
+
puts "Master hash: #{master_hash}"
|
|
68
|
+
[hash, block_hash, master_hash]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def update_block_connections
|
|
72
|
+
block.update(connections: (block.connections + 1))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def ticket_created?
|
|
76
|
+
hash, block_hash, master_hash = generate_user_acceptable_hash
|
|
77
|
+
@ticket = Ticket.new(user_id: user_id, status: :active, pool_id: pool_id,
|
|
78
|
+
time_ref: time_ref, user_acceptable_hash: hash,
|
|
79
|
+
confirmation_hash: master_hash, block_hash: block_hash,
|
|
80
|
+
transaction_id_list: generate_transaction_id_list)
|
|
81
|
+
@ticket.save ? true : false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def ticket_exists?
|
|
85
|
+
Ticket.find_by(user_id: user_id, pool_id: pool_id, status: :active).present?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateWalletService < ApplicationService
|
|
4
|
+
def initialize(user_id)
|
|
5
|
+
@user_id = user_id
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def call
|
|
10
|
+
return if wallet_exists?("user_id", user_id)
|
|
11
|
+
create_wallet
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
attr_reader :user_id
|
|
16
|
+
|
|
17
|
+
def create_wallet
|
|
18
|
+
Wallet.create(user_id: user_id) ? true : false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TransactionToBlockService < ApplicationService
|
|
4
|
+
def initialize(receiver_key, sender_key, amount, block_id)
|
|
5
|
+
@receiver_key = receiver_key
|
|
6
|
+
@sender_key = sender_key
|
|
7
|
+
@amount = amount
|
|
8
|
+
@block_id = block_id
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call
|
|
12
|
+
create_transaction_to_block
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
attr_reader :receiver_key, :sender_key, :amount, :block_id
|
|
17
|
+
|
|
18
|
+
def create_transaction_to_block
|
|
19
|
+
return false unless wallets_present?
|
|
20
|
+
unless block_confirmed?
|
|
21
|
+
transaction.block_id = block.id
|
|
22
|
+
pool.amount += transaction.fee
|
|
23
|
+
pool.save
|
|
24
|
+
transaction_saved?
|
|
25
|
+
else
|
|
26
|
+
refresh_block
|
|
27
|
+
create_transaction_to_block
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def block
|
|
32
|
+
@block ||= Block.find(block_id)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def pool
|
|
36
|
+
block.pool
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def fee
|
|
40
|
+
(amount.to_f * 0.10).round(2)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def transaction
|
|
44
|
+
@transaction ||= Transaction.new(receiver_key: receiver_key, sender_key: sender_key, amount: amount, block_id: block.id, fee: fee)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def block_confirmed?
|
|
48
|
+
block.master_hash.present?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def transaction_saved?
|
|
52
|
+
transaction.save ? true : false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def wallets_present?
|
|
56
|
+
wallet_exists?("pr_key", receiver_key) && wallet_exists?("pv_key", sender_key)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def refresh_block
|
|
60
|
+
@block = Block.where(master_hash: nil).last
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<div class=" h-full w-full px-5 pt-6 pb-20 overflow-y-auto">
|
|
2
|
+
<div class="mb-3">
|
|
3
|
+
<h1 class="text-3xl text-white font-bold">Blocks</h1>
|
|
4
|
+
<p class="text-sm text-purple-500 uppercase font-bold">Last Blocks</p>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<% @blocks.each do |block| %>
|
|
8
|
+
<% if block %>
|
|
9
|
+
<div class="mb-5">
|
|
10
|
+
<a href="<%= url_for(block) %>" class="block rounded-lg relative p-5 transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "gimage.png" %>) center; background-size: cover;">
|
|
11
|
+
<div class="absolute top-0 right-0 -mt-3 mr-3">
|
|
12
|
+
<div class="rounded-full bg-indigo-500 text-white text-xs py-1 pl-2 pr-3 leading-none"><i class="mdi mdi-fire text-base align-middle"></i> <span class="align-middle">FRESH</span></div>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="h-48"></div>
|
|
15
|
+
<h2 class="text-white text-2xl font-bold leading-tight mb-3 pr-5">Block <%= block.id %></h2>
|
|
16
|
+
<div class="flex w-full items-center text-sm text-gray-300 font-medium">
|
|
17
|
+
<div class="flex-1 flex items-center">
|
|
18
|
+
<div class="rounded-full w-8 h-8 mr-3" style="background: url(<%= asset_path "logo.png" %>) center; background-size: cover;"></div>
|
|
19
|
+
<% if block.master_hash.present? %>
|
|
20
|
+
<div class="text-white" style="font-weight: 550;" >confirmed</div>
|
|
21
|
+
<% else %>
|
|
22
|
+
<div class="text-white" style="font-weight: 600; font-size: 25px;" >unconfirmed</div>
|
|
23
|
+
<% end %>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div><i class="mdi mdi-thumb-up text-black"></i><%= block.transactions.count %> transactions</div>
|
|
27
|
+
</div>
|
|
28
|
+
</a>
|
|
29
|
+
</div>
|
|
30
|
+
<% end %>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<div class="mb-3">
|
|
34
|
+
<h1 class="text-3xl text-white font-bold">HUB</h1>
|
|
35
|
+
<p class="text-sm text-purple-500 uppercase font-bold">explore</p>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="flex -mx-1 mb-5">
|
|
39
|
+
|
|
40
|
+
<div class="w-1/2 px-1 text-center">
|
|
41
|
+
<a href="blocks" class="block mb-2 p-5 rounded overflow-hidden transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space.jpg" %>) center; background-size: cover;">
|
|
42
|
+
<div class="h-24"></div>
|
|
43
|
+
<div class="text-lg font-bold text-black leading-tight glitch" data-glitch="Blockchain">Blockchain</div>
|
|
44
|
+
</a>
|
|
45
|
+
<a href="transactions" class="block mb-2 p-5 rounded overflow-hidden transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space_two.jpg" %>) center; background-size: cover;">
|
|
46
|
+
<div class="h-32"></div>
|
|
47
|
+
<div class="text-lg font-bold text-white leading-tight glitch" data-glitch="Transactions">Transactions</div>
|
|
48
|
+
</a>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<% if user_signed_in? %>
|
|
52
|
+
<div class="w-1/2 px-1 text-center">
|
|
53
|
+
<a href="wallets" class="block mb-2 p-5 rounded overflow-hidden transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space_th.jpg" %>) center; background-size: cover;">
|
|
54
|
+
<div class="h-32"></div>
|
|
55
|
+
<h3 class="text-lg font-bold text-white leading-tight glitch" data-glitch="Wallet">Wallet</h3>
|
|
56
|
+
</a>
|
|
57
|
+
<a href="mining_profile" class="block mb-2 p-5 rounded overflow-hidden text-center transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space_four.jpg" %>) center; background-size: cover;">
|
|
58
|
+
<div class="h-24"></div>
|
|
59
|
+
<div class="text-lg font-bold text-white leading-tight glitch" data-glitch="Mining Profile">Mining Profile</div>
|
|
60
|
+
</a>
|
|
61
|
+
</div>
|
|
62
|
+
<% else %>
|
|
63
|
+
<div class="w-1/2 px-1 text-center">
|
|
64
|
+
<a href="/users/sign_in" class="block mb-2 p-5 rounded overflow-hidden transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space_th.jpg" %>) center; background-size: cover;">
|
|
65
|
+
<div class="h-32"></div>
|
|
66
|
+
<h3 class="text-lg font-bold text-white leading-tight glitch" data-glitch="Login">Login</h3>
|
|
67
|
+
</a>
|
|
68
|
+
<a href="/users/sign_up" class="block mb-2 p-5 rounded overflow-hidden transform transition-all duration-300 scale-100 hover_scale-95" style="background: url(<%= asset_path "space_four.jpg" %>) center; background-size: cover;">
|
|
69
|
+
<div class="h-24"></div>
|
|
70
|
+
<h3 class="text-lg font-bold text-white leading-tight glitch" data-glitch="Sign Up">Sign Up</h3>
|
|
71
|
+
</a>
|
|
72
|
+
</div>
|
|
73
|
+
<% end %>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= render 'featured_board'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
.text-white.text-center
|
|
2
|
+
p[style="font-size: 20px;font-weight: 550;"]
|
|
3
|
+
/ outersapce logo rounded image
|
|
4
|
+
= image_tag("logo.png", class: "rounded-full h-20 w-20", style: "margin: 0 auto;")
|
|
5
|
+
strong
|
|
6
|
+
= "#{current_user.username}'s"
|
|
7
|
+
h1 Mining profile
|
|
8
|
+
br
|
|
9
|
+
.flex
|
|
10
|
+
.w-1/2.text-center.mr-4.mt-4.border-2.border-purple-500.rounded.p-4.bg-purple-500
|
|
11
|
+
p[style="font-size: 20px; font-weight: 550;"]
|
|
12
|
+
strong Wallet
|
|
13
|
+
p[style="font-size: 16px;"]
|
|
14
|
+
strong
|
|
15
|
+
= "Balance: #{current_user.wallet.balance}"
|
|
16
|
+
p[style="font-size: 16px;"]
|
|
17
|
+
strong
|
|
18
|
+
= "Address: #{current_user.wallet.pr_key}"
|
|
19
|
+
.w-1/2.text-center.mr-4.mt-4.border-2.border-purple-500.rounded.p-4.bg-purple-500
|
|
20
|
+
p[style="font-size: 20px;font-weight: 550;"]
|
|
21
|
+
strong API
|
|
22
|
+
p[style="font-size: 16px;"]
|
|
23
|
+
strong Key:
|
|
24
|
+
= current_user.api_key
|
|
25
|
+
p[style="font-size: 16px;"]
|
|
26
|
+
strong Secret:
|
|
27
|
+
= current_user.api_secret
|
|
28
|
+
p[style="font-size: 16px;"]
|
|
29
|
+
strong
|
|
30
|
+
= "Has a ticket? #{@ticket.present?}"
|
|
31
|
+
- unless @ticket.present?
|
|
32
|
+
br
|
|
33
|
+
= link_to "Get a ticket", new_ticket_path, class: "px-4 py-2 rounded bg-gray-800 hover_bg-black text-white"
|
|
34
|
+
br
|
|
35
|
+
br
|
|
36
|
+
.flex
|
|
37
|
+
.w-1/3.text-center.mr-4.mt-4.border-2.border-purple-500.rounded.p-4.bg-purple-500
|
|
38
|
+
p[style="font-size: 20px;font-weight: 550;"]
|
|
39
|
+
strong Acceptable Words
|
|
40
|
+
- @words.each do |word|
|
|
41
|
+
p[style="font-size: 16px;"]
|
|
42
|
+
strong
|
|
43
|
+
= word
|
|
44
|
+
.w-1/3.text-center.mr-4.mt-4.border-2.border-purple-500.rounded.p-4.bg-purple-500
|
|
45
|
+
p[style="font-size: 20px;font-weight: 550;"]
|
|
46
|
+
strong Acceptable Number Sequences
|
|
47
|
+
- @numbers.each do |sequence|
|
|
48
|
+
p[style="font-size: 16px;"]
|
|
49
|
+
strong
|
|
50
|
+
= sequence
|
|
51
|
+
.w-1/3.text-center.mr-4.mt-4.border-2.border-purple-500.rounded.p-4.bg-purple-500
|
|
52
|
+
p[style="font-size: 20px;font-weight: 550;"]
|
|
53
|
+
strong Acceptable Symbol Sequences
|
|
54
|
+
- @symbols.each do |sequence|
|
|
55
|
+
p[style="font-size: 16px;"]
|
|
56
|
+
strong
|
|
57
|
+
= sequence
|
|
58
|
+
br
|
|
59
|
+
br
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
= form_with(model: @block) do |form|
|
|
2
|
+
- if @block.errors.any?
|
|
3
|
+
div style="color: red"
|
|
4
|
+
h2 = "#{pluralize(@block.errors.count, "error")} prohibited this block from being saved:"
|
|
5
|
+
ul
|
|
6
|
+
- @block.errors.each do |error|
|
|
7
|
+
li = error.full_message
|
|
8
|
+
|
|
9
|
+
div
|
|
10
|
+
= form.label :nonce, style: "display: block"
|
|
11
|
+
= form.number_field :nonce
|
|
12
|
+
|
|
13
|
+
div
|
|
14
|
+
= form.label :previous_hash, style: "display: block"
|
|
15
|
+
= form.text_field :previous_hash
|
|
16
|
+
|
|
17
|
+
div
|
|
18
|
+
= form.label :block_data, style: "display: block"
|
|
19
|
+
= form.text_area :block_data
|
|
20
|
+
|
|
21
|
+
div
|
|
22
|
+
= form.label :connections, style: "display: block"
|
|
23
|
+
= form.text_field :connections
|
|
24
|
+
|
|
25
|
+
div
|
|
26
|
+
= form.submit
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
.text-center.text-white
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
h1[style="font-size: 25px; font-weight: 600;"] Blockchain
|
|
5
|
+
|
|
6
|
+
#blocks
|
|
7
|
+
- @blocks.each do |block|
|
|
8
|
+
== render block
|
|
9
|
+
br
|
|
10
|
+
p
|
|
11
|
+
= link_to "Show this block", block, class: "px-4 py-2 rounded bg-purple-500 hover_bg-purple-700 text-white"
|
|
12
|
+
br
|