Bitcoin Forum

Local => Альтернативные криптовалюты => Topic started by: Mitch on December 16, 2017, 08:11:53 PM



Title: Изучаем Solidity
Post by: Mitch on December 16, 2017, 08:11:53 PM
Поглядев на хайп вокруг блокчейна, подумал я а не переквалифицироваться ли в блокчейн программисты?
Выбор пал на Solidity - язык смарт контрактов эфириума.

Почему: Смарт контракты это очень перспективная технология, уже сейчас используется и можно найти хорошо оплачиваемые заказы, а в будущем еще лучше будет.
Эфир же лидер пока далеко опережающий по популярности другие платформы с смарт контрактами.

Также в этой идее мне понравилось то, что тут короткий стек технологий и отсутствие тяжелого наследия старых версий. Например если изучать веб програмирование, то там в стек технологий надо сразу JS+SQL+язык.

А тут достаточно просто одного solidity плюс понимание работы блокчейна и криптографии.
Минус в том что с документацией, книгами курсами дела пока обстаят не очень, особенно на русском.

В этом топике буду описывать свои успехи и выкладывать ссылки на хорошие обучающие материалы.

1. Язык Solidity: Неllo World (Урок 1) (https://golos.io/ru--obrazovanie/@rusldv/yazyk-solidity-nello-world-urok-1)
очень понравилось изложение материала, поэтому поставлю пока первым в списке.
2. [Russian] Руководство по Solidity (https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity)
Это перевод официальной документации.
Много инфы, но встречаются не переведенные с английского куски
3. Официальная документация на английском (https://solidity.readthedocs.io/en/develop/)

Вот еще пачка статей на русском:
https://habrahabr.ru/post/327236/
https://habrahabr.ru/post/312008/
https://habrahabr.ru/company/neobit/blog/324456/
https://habrahabr.ru/company/neobit/blog/324456/
https://habrahabr.ru/post/335710/


Title: Re: Изучаем Solidity
Post by: Mitch on December 16, 2017, 08:23:06 PM
Сам  с програмированием знаком, но довольно поверхностно.
Мне нравится изучать язык реализовывая конкретную небольшую задачу.

На solidity я хочу написать контракт честной лотереи, на результат розыгрыша которой владелец контракта не сможет повлиять.
Сама идея такая:

Все кто хочет участвовать в лотерее отсылают на адресс смарт контракта эфириум, кто сколько хочет.
Каждый 1 wei (минимальный обьем эфира) получает "билет в лотерею".
В момент розыгрыша, ну например каждый 100й блок главной ветки смарт контракт случайным образом определяет победителя и отсылает ему все деньги за вычитом 10% которые он скидывает мне.

Идея вроде простая :)
Теперь читать документацию и начинать писать и тестировать.


Title: Re: Изучаем Solidity
Post by: Coin-1 on December 17, 2017, 03:22:06 AM
Хорошие туториалы, написано простым языком, всё понятно. Но Solidity - это привязка к конкретной монете Ethereum.


Title: Re: Изучаем Solidity
Post by: Mitch on December 17, 2017, 09:47:38 AM
Хорошие туториалы, написано простым языком, всё понятно. Но Solidity - это привязка к конкретной монете Ethereum.
Насколько я знаю, универсального языка смарт контрактов и не существует, у каждой монеты свой.
У меня есть задача - занять какую то узкую нишу в программировании, где платят хорошие деньги, и чтоб пониже порог входа по объему технологий которые надо изучить.
Можете предложить вариант лучше?


Title: Re: Изучаем Solidity
Post by: Mitch on December 17, 2017, 12:39:19 PM
Гуглил как же выяснять кто нам слал деньга на контракт и как работать с временем, нагуглил еще один сайт с уроками по смарт контрактам
http://inaword.ru/smart-kontrakty/

Итак, можно используя "fallback function" (которая вызывается в момент прихода эфира на контракт)
записывать в переменные состояния новую запись.
Данные логично хранить в структуре вроде
mapping (address => uint256) client_tickets;
Надо теперь глубже с массивами разобраться.
Архитектурно получается вот так
адрес1 -> сумма1
адрес2 -> сумма2
.....
адресN -> сумма_N
значит в момент розыгрыша надо:
- сложить все полученные суммы от сумма1 до сумма_N
- сгенерить случайное число X, такое что 0 < X < N
- X соответственно покажет адрес победителя которому надо отдать приз (складываем суммы начиная с первой полученной и до тех пор пока сумма не станет больше X)

Для определения а не пора ли сделать розыгрыш можно использовать now

интересные вопросы над которыми я думал:
1. Откуда now берет время?
С виртуальной машины майнера который взялся исполнять контракт?
Может ли быть на этой VM неправильное время, может не стоит к времени привязываться а ориентироваться по номерам блоков..

2. Могут ли возникнуть коллизия когда одновременно 2 человека послали деньги на контракт (ведь очередность прихода денег у нас фактически определяет "номер билета в лотерее") ?
Исходя из моего понимания логики работы блокчейна, от этого мы застрахованы.
Даже если в физическом мире они отправили деньги одновременно, транзакции в блоке все равно будут записаны последовательно.


Title: Re: Изучаем Solidity
Post by: torwig on December 17, 2017, 08:36:01 PM
Как Вы будете генерировать случайное число в смарт-контракте?
По поводу неправильного времени у майнера: если оно будет таковым, скорее всего блок не будет подтвержден остальными майнерами и соответственно не будет принят в цепочку.


Title: Re: Изучаем Solidity
Post by: Mitch on December 17, 2017, 10:22:52 PM
Еще не добрался до этого вопроса.
Погуглил сейчас - пишут что встроенной функции random() нету в solidity
и что это вообще может быть проблемой, тк VM одна и таже и непонятно откуда взять случайность.

Было бы логично использовать nonce из текущего блока в момент розыгрыша, но пишут что к этому значению нет доступа изнутри контракта (https://ethereum.stackexchange.com/questions/2701/do-the-contracts-of-ethereum-have-the-access-to-the-nonce-of-the-blocks).
Это кстати меня удивило.

Можно например использовать в качестве случайных данных адреса с которых участники присылали эфир.
Конечно, если движухи мало, и атакующий имеет возможность сделать сам гарантированно несколько последних транзакций, то он может повлиять нужным образом используя свои адреса.

Смотрю на доступные переменные, думаю может использовать block.blockhash (function(uint) returns (bytes32)): hash of the given block - only works for 256 most recent blocks
Например в 12:00 "продажу билетов завершаем"
Ждем 10 минут, и используем как базу для случайного числа хеш блока найденого после 12:05


Title: Re: Изучаем Solidity
Post by: TechPriest on December 17, 2017, 11:29:41 PM
Насколько я знаю, универсального языка смарт контрактов и не существует, у каждой монеты свой.
У меня есть задача - занять какую то узкую нишу в программировании, где платят хорошие деньги, и чтоб пониже порог входа по объему технологий которые надо изучить.
Можете предложить вариант лучше?

Без обид, но вы не туда пришли в таком случае. Все, что вы выучите, скорее всего пойдет вам на пользу в плане личностного развития, но не карьерного.
Вы хотите работать в блокчейне, но вопрос: Почему вы не работаете программистом просто так? Например фуллстак разработчиком? Или не пишете контроллеры на плюсах?

Проблема того же Солидити, что он высокоуровневый. Он довольно сырой и забагован, притом, мало кто сейчас понимает как Солидити взаимодействует с системой на низком уровне (большинство "взломов" смартконтрактов, их некорректной работы связанны именно с этим) Человек видит облочку, пишет контракт. Если смотреть по программе - все корректно и хорошо. Контракт запускается в сеть, и хоп, что-то вылазит. Или не вылазит, а кто-то пользуется тем, что на низком уровне все работает не совсем так.

Например, у меня в закладках была статья с примерами так называемого "говнокодинга" на Солидити. Ужас был в том, что по коду все выглядело красиво, но работало не так. Из того что помню, был код, элементарный, который через Н дней отправлял платеж на некий адрес. Но так как первая транзакция не подтвердилась (не успела или сеть была загружена) контракт наспамил еще пару транзакций пока баланс не опустел.

Что бы писать на Солидити, нужно понимать низкие уровни. Поэтому я бы вам советовал написать некий смарт контракт с помощью сети Биткоина (его язык позволяет писать элементарные контракты). Это намного поможет вашему пониманию.


Title: Re: Изучаем Solidity
Post by: Mitch on December 18, 2017, 08:34:44 AM
20 лет назад я изучал турбо паскаль годик в школе
потом еще чуток сам изучал C
потом когда работал админом немного писал на баше
а когда занимался вебмастерской деятельностью иногда что то правил по мелочи в php особо не углубляясь.

Вообщем - я не программист в текущий момент.
Поэтому я не могу быть фулстек разработчиком.
Мне этот самый стек надо старательно изучить, и конкурировать прийдется с фулсткек разработчиками которые уже варятся в этой теме годами.

Была такая мысль, летом я попроходил на хекслет половину php стека и часть курса по js и понял что там еще копать и копать до работы в продакшене за деньги.

Тут мне вопервых кажется ниже порог входа - меньше информации которую нужно изучить.
Вовторых - мое отставание от других программистов в нише будет существенно меньше, тк ниша сама по себе новая.
А почасовка у блокчейн программистов сейчас должна быть в несколько раз выше чем у аналогичных по уровню фулстек веб разработчиков.

Изучить как работает блокчейн на низком уровне я конечно планирую, это интересно.


Title: Re: Изучаем Solidity
Post by: m2017 on December 18, 2017, 08:59:22 AM
Сам  с програмированием знаком, но довольно поверхностно.
Мне нравится изучать язык реализовывая конкретную небольшую задачу.

На solidity я хочу написать контракт честной лотереи, на результат розыгрыша которой владелец контракта не сможет повлиять.
Сама идея такая:

Все кто хочет участвовать в лотерее отсылают на адресс смарт контракта эфириум, кто сколько хочет.
Каждый 1 wei (минимальный обьем эфира) получает "билет в лотерею".
В момент розыгрыша, ну например каждый 100й блок главной ветки смарт контракт случайным образом определяет победителя и отсылает ему все деньги за вычитом 10% которые он скидывает мне.

Идея вроде простая :)
Теперь читать документацию и начинать писать и тестировать.

а ты харошшШ... решил запилить "налог для дураков" на блокчэйне...


Title: Re: Изучаем Solidity
Post by: atlantik on December 18, 2017, 09:07:26 AM
Привет, встречал небольшой курс на сайте http://inaword.ru по солибиту, посмотри может что подчерпнешь


Title: Re: Изучаем Solidity
Post by: Mitch on December 18, 2017, 01:04:26 PM
ага, его видел, часть уроков прочел.
полезный курс


Title: Re: Изучаем Solidity
Post by: Ranyar on December 18, 2017, 01:09:02 PM
ОП, топик полезный, но наверное будет гораздо лучше перенсти его в специализированную ветку "Кодеры", где сидит больше программистов, чем трейдеров.


Title: Re: Изучаем Solidity
Post by: Mitch on December 18, 2017, 01:15:26 PM
Ну я вообще то его там и делал.
Модератор зачем то перенес сюда.


Title: Re: Изучаем Solidity
Post by: TechPriest on December 18, 2017, 02:04:20 PM
Тут мне вопервых кажется ниже порог входа - меньше информации которую нужно изучить.
Вовторых - мое отставание от других программистов в нише будет существенно меньше, тк ниша сама по себе новая.
А почасовка у блокчейн программистов сейчас должна быть в несколько раз выше чем у аналогичных по уровню фулстек веб разработчиков.

Вот здесь и кроется проблема. Ведь все наоборот.
Для работы в сфере блокчейна нужно и вэб хорошо знать, и криптографию понимать и еще много чего. Среднее требование это что-то в стиле: написать сайт который бы принимал биткоины. Тоесть нужно и сайт сверстать, и платежку подключить.
Во вторых, сейчас предложение по работникам превышает спрос в 2.5 раза. Или около того. То, что вы сможете сделать сможет сделать любой другой конкурент, поэтому выхлоп будет небольшой. А то, за что в теории хорошо заплатят вы не сможете сделать как минимум года два, так как нельзя с нуля сесть и написать что-то серъезное.

не бросайте обучение, это будет полезно, но и не надейтесь что за вашу лоторею вас сразу заберут в самый успешный стартап и вы будете получать больше синьора в обычной конторе. Тоесть, будьте к этому морально готовы.
Конкуренция здесь сейчас очень большая, это со стороны кажется, что сфера новая. Новой она была в 10-11 годах. Ну или с момента появления Эфира если мы говорим об Эфире.


Title: Re: Изучаем Solidity
Post by: Mitch on December 18, 2017, 02:12:12 PM
Конечно я вначале буду писать что то для себя, а там видно будет.
Как минимум, полученный опыт позволит мне более профессионально нанимать программистов, когда это опять потребуется.


Title: Re: Изучаем Solidity
Post by: Mitch on December 19, 2017, 02:45:09 PM
Возник вопрос, mapping итерируемый или нет?
Если нет, то получается в лотерее для хранения поступлений нужно использовать двойной mapping.
Первый ключ порядковый номер поступления денег и каждому номеру соответствует пара адресс и сумма.
mapping (ticket_number => mapping (address => uint256)) client_tickets;

Нумеровать начиная с 0, и еще завести переменную в которой хранить
номер последнего билета добавленного в базу.
last_ticket_number uint256;

Выглядит как изобретение велосипеда, который давно должен существовать.
Может mapping итерируемый все же, а мне это пока в доках не встретилось.
Пока решил последовательно пройти все уроки с inaword.ru (http://inaword.ru/smart-kontrakty/)
Читаю, вникаю, все примеры пробую на работоспособность в remix.

Разбирать рабочие примеры получается эффективнее чем последовательно читать доки и по ней пытаться сделать сразу.


Title: Re: Изучаем Solidity
Post by: Mitch on December 19, 2017, 04:05:20 PM
В комментах на  inaword нашел ответ на возникший вопрос:
А как же подключать библиотеки в remix?

Надо добавить в начале кода импорт библиотеки, причем можно напрямую с github!
Пример:
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/MintableToken.sol";

Такая запись так же подгружает всё на что MintableToken.sol ссылается внутри.

Задумался о том, как же надо этим правильно пользоваться в продакшине, где уже реальные деньги.
Стоит себе в git наверное форкать все библиотеки, чтоб они там были в определенном "застывшем состоянии" зафиксированы, и регулярно мониторить апдейты и вручную утаскивать к себе тестить.

Чтоб случайно не накатить на продакшен со своим косметическим изменением какие то фундаментальные в библиотеке и потом удивлятся если все сломалось.


Title: Re: Изучаем Solidity
Post by: Mitch on December 21, 2017, 03:32:29 PM
Думал над архитектурой данных своей тестовой лотереи.
Пришел к мысли что надо сделать фиксированную цену "лотерейного билета".
Вопервых, цена билета должна быть значительно выше средней комиссии за транзакцию эфира, ну хотя
бы в 20 раз, чтоб не получилось так что получилась сплошная раздача денег майнерам на микротранзакциях.
Сейчас комиссия менее 0.2$
Если бы не комиссия то я бы делал билеты примерно по 1$
А с учетом комиссии значит надо делать минималку около 5-10$.
Курс эфира сейчас около 400-800$, значит пусть будет цена 1го билета в лотерею = 0.01eth

При поступлении эфира на кошелек контракта вызываем fallback функцию
  function() external payable {
тут надо:
1. выяснить на какое количество билетов хватает входящего платежа, и записать за номером кошелька участника номера лотерейных билетов которые он приобрел.
2. сохранить эти данные в контракте до момента розыгрыша.
стуруктура данных напрашивается
mapping (uint => address  ) client_tickets;
индексное поле целочисленное без знака uint это номер билета лотереи, а address это кошелек участника которому надо выдать приз если билет выиграет.
Номера билетов присваиваем последовательно, в отдельной переменной контракта сохраняем последний выданный номер билета.
uint ticket_count;
В конструктор контракта вписываем для определенности
ticket_count = 0;

Если участник прислал например 0.05 эфира то выдаем ему 5 билетов, записав подряд 5 записей в наш mapping с данными.
Мне конечно не очень нравится, что я вроде делаю неоптимальные записи, экономнее то записать
кошелек_N:0.05
чем
1:кошелек_N
2:кошелек_N
3:кошелек_N
4:кошелек_N
5:кошелек_N

Если часто участники будут покупать не один билет а сразу десятки или сотни, то неоптимальность значительная.
Если большинство будет брать 1 билет, то все красиво конечно.

Плюс схемы с явным отдельным номером билета - более простое понимание кода и данных читателем контракта. А его хочется сделать максимально понятным, чтоб любой желающий мог понять как работает контракт лотереи, не ломая голову над усложненной логикой.

Что делать с остатком если участник прислал денег на дробное количество билетов?
Вариантов тут 3
1. вернуть сдачу (если она больше чем комиссия)
2. прибавить к призовому фонду
3. забрать организатору
Выберу 2й пункт.



Title: Re: Изучаем Solidity
Post by: Mitch on December 21, 2017, 03:40:40 PM
Контракт думаю сделать постоянно живым, а розыгрыш лотереи примерно раз в сутки.
Те транзакции которые пришли на контракт после розыгрыша пусть автоматически попадают в следующий розыгрышь.

В первой версии у меня не будет ничего кроме контракта на solidity
и я не могу например на сервере по крону запускать скрипт который бы обратился в блокчейн эфириума и вызвал функцию "вычислить победителя и выплатить".
Поэтому думаю в контракте в fallback функцию добавить проверку текущего времени и если с момента прошлого розыгрыша прошло более 24 часов, то производить розыгрыш.

В конструктор контракта добавить первичную инициализацию переменной где сохраняем время последнего розыгрыша = дата запуска лотереи.


Title: Re: Изучаем Solidity
Post by: Mitch on December 21, 2017, 04:03:26 PM
Для розыгрыша нужна функция в которую надо передать полное количество билетов участвующих в розыгрыше и на выходе получить случайный номер билета.
random(max_ticket_number);


Но в solidity нет встроенного random, получается его надо написать.
И заняться этим в первую очередь, все таки случайный выбор архиважная часть лотереи.

Итак мы хотим функцию random куда надо передать max_ticket_number и на выходе целое число получить от 1 до max_ticket_number
Я решил попробовать извлечь случайные данные из block.blockhash текущего блока.
Вот такой код я написал в Remix
Хеш беру не текщего блока а предидущего, тк текущий выдает одни нули, а предидущий дал
0x18676e992055c057538d59b378271bb4eacdb7f6abf9e815fd63255dc11166b6
Выглядит очень случайно!

pragma solidity ^0.4.13;
contract Random {
    function get_block_number() public constant returns (uint) {
        return block.number;
    }
        function get_blockhash() public constant returns (bytes32) {
        return block.blockhash(block.number);
    }

}

Осталось перевести byte32 в uint и произвести деление с остатком.
Ну и протестить на случайность, взяв такой рандом за последние 1000 блоков и посмотреть какие он выдаст цифры от 1 до 10 и посмотреть нет ли отклонений выдаче.


Title: Re: Изучаем Solidity
Post by: Mitch on December 22, 2017, 02:19:47 PM
Пишу читаю, и вдруг я вспомнил про code convetions (http://solidity.readthedocs.io/en/develop/style-guide.html).
Решил что надо глянуть как принято в solidity писать, и писать так, а не как попало.
Мда, там многобукв :)
Пока запомню и внедрю самое важное:

Функции надо называть  разделяя слова заглавными буквами, типа function thisFunctionHasLotsOfArguments()
а в переменных использовать подчеркивания long_variable

И использовать пробелы а не табы (wtf?!), ну ок, стандарт есть стандарт.


Title: Re: Изучаем Solidity
Post by: Mitch on December 22, 2017, 03:26:36 PM
Игрался с рандомом, написал вот такой код:
Code:
pragma solidity ^0.4.13;
contract Random {
    uint max_ticket_number;
    uint shift_block;
    uint winner_number;
   
    function Random() public {
       max_ticket_number = 100;
       shift_block = 1;
    }
   
    function setMaxTicketNumber(uint new_max_ticket_number) public {
        max_ticket_number = new_max_ticket_number;
    }
   
    function getWinnerNumber() public {
        uint base_random = uint(block.blockhash(block.number - shift_block));
        //shift_block++;
        winner_number = base_random%max_ticket_number;
    }
    function printWinnerNumber() public constant returns (uint) {
        return winner_number;
    }

    function getShift() public constant returns (uint) {
        return shift_block;
    }
   
    function getBlockNumber() public constant returns (uint) {
        return block.number;
    }
        function getBlockhash() public constant returns (uint) {
        return uint(block.blockhash(block.number - shift_block));
    }

}

Экспериментально выяснил, что когда вызываю функцию изменяющую контракт, то есть объявленную без constant то в блокчейне Remix возникает новый блок.
Такие функции Remix отображает красными квадратиками.
function getWinnerNumber() вычисляет победителя, но почему то не хочет Remix отобразить результат из нее.
Сделал поэтому printWinnerNumber() она чисто отображает результат.
Жмем последовательно, видим, что по хешу блока выдаются разные случайные значения в заданном диапазоне.

Нет ли у потенциального атакующего возможности узнать хеш блока который мы используем при вычислении победителя до отправки транзакции "покупающей билет"?
Этот вопрос надо осознать.
Если наш контракт будет вызван после того как транзакция которая запустит механизм вычисления победителя включена в блок, то по идее мы и будем использовать хеш блока в который она включена, и соответственно в момент отправки транзакции этот блок еще не существовал.
Это если блоки в эфире делаются строго последовательно, а я что то не уверен в этом.. как то же выполнение этих смарт контрактов распаралеливается, а то бы скорости не было вообще.
Надо изучить тут теорию работы эфира значит глубже.


Title: Re: Изучаем Solidity
Post by: bomj on September 25, 2018, 02:11:37 PM
С удовольствием прочитал данный топик.
Как хороший рассказ. Жаль что оборвался.
Интересно было бы узнать конец истории....


Title: Re: Изучаем Solidity
Post by: circuswp on September 25, 2018, 02:35:46 PM
Отличная тема, действительно интересно - ждём продолжения.
Сам хотел солидол изучать, надо написать пару смарт контрактов для тестирования.


Title: Re: Изучаем Solidity
Post by: Mitch on September 25, 2018, 05:54:44 PM
Меня убедили в том, что на одном solidity далеко не уедешь.
Крайне сложно найти клиента которому бы нужен был бы чисто смартконтракт, а не сайт\приложение + смартконтракт.

И в январе я решил что надо изучить Java.
Вот все еще изучаю.
Сначала проходил курсы на hexlet, все что там тогда было по java, курс закончился, а я еще был далек от того чтобы сделать самый простенький сайт на java.
Потом я еще почти 3 месяца занимался на javarush.
Чтож, это было весьма полезно, теория полученая на hexlet отлично дополнилась огромной кучей задачек которые я решал тут сотнями.
Я добрался до 15го уровня javarush
Но.. до java-web было все бесконечно далеко, и в будущих уроках как то не проглядывалось что меня начнут этому учить.

Я пошел на форум программистов и нашел себе учителя, на java-web.
Занимаемся уже 2 недели, и конечно с живым человеком обучение идет гораздо интереснее чем по курсам.
Мне кажется что я уже близок к продакшену и за пару месяцев напишу первый проект который у меня был запланирован.


Title: Re: Изучаем Solidity
Post by: bomj on September 25, 2018, 06:05:43 PM
...Я пошел на форум программистов и нашел себе учителя, на java-web.
Занимаемся уже 2 недели, и конечно с живым человеком обучение идет гораздо интереснее чем по курсам.
Мне кажется что я уже близок к продакшену и за пару месяцев напишу первый проект который у меня был запланирован.
Вы все правильно делаете, не останавливайтесь.
Но все же не забывайте иногда выкладывать продолжение истории.
Я и так случайно на нее наткнулся, пролистывая форум на год назад.
Это поучительно и познавательно.
Удачи.


Title: Re: Изучаем Solidity
Post by: deniben on September 25, 2018, 08:06:23 PM
Меня убедили в том, что на одном solidity далеко не уедешь.
Крайне сложно найти клиента которому бы нужен был бы чисто смартконтракт, а не сайт\приложение + смартконтракт.

И в январе я решил что надо изучить Java.
Вот все еще изучаю.
Сначала проходил курсы на hexlet, все что там тогда было по java, курс закончился, а я еще был далек от того чтобы сделать самый простенький сайт на java.
Потом я еще почти 3 месяца занимался на javarush.
Чтож, это было весьма полезно, теория полученая на hexlet отлично дополнилась огромной кучей задачек которые я решал тут сотнями.
Я добрался до 15го уровня javarush
Но.. до java-web было все бесконечно далеко, и в будущих уроках как то не проглядывалось что меня начнут этому учить.

Я пошел на форум программистов и нашел себе учителя, на java-web.
Занимаемся уже 2 недели, и конечно с живым человеком обучение идет гораздо интереснее чем по курсам.
Мне кажется что я уже близок к продакшену и за пару месяцев напишу первый проект который у меня был запланирован.

Классно, что на это не закончили. Я тоже кстати  изучаю java и solidity