osbc 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|