
Текстът е продължение на серия статии, в които разглеждам структурата на (предполагаемо) подготвяната за излизане тази година разпределена мрежа Telegram Open Network (TON). В описах най-базовото й ниво — начина на взаимодействие между възлите.
За всеки случай напомням, че нямам отношение към разработването на тази мрежа и целият материал е извлечен от открит (макар и непроверен) източник — (има и приложен , в която накратко са изложени основните моменти), появила се в края на миналата година. Обемът на информацията в този документ, на мое мнение, свидетелства за неговата автентичност, макар че няма официални потвърждения за това.
Днес ще разгледаме основния компонент на TON — блокчейн.
Основни понятия
Акаунт (account). Набор от данни, идентифициран от 256-битов номер account_id (най-често това е публичният ключ на собственика на акаунта). В базовия случай (вж. по-долу нулев блокчейн), под тези данни се разбира балансът на потребителя. „Вземането“ на конкретен account_id може да стане от всеки, но променянето на неговата стойност е възможно само при определени правила.
Смарт-контракт (smart-contract). По същество — частен случай на акаунт, допълнен с код на смарт-контракта и хранилище на неговите променливи. Ако при „портфейла“ може да се кредитират и дебитират средства по сравнително прости и предварително определени правила, то в случай на смарт-контракт тези правила са записани под формата на неговия код (на някакъв Тюринг-пълен език за програмиране).
Състояние на блокчейна (state of blockchain). Сбор на състоянията на всички акаунти/смарт-контракти (в абстрактен смисъл — хеш-таблица, където ключовете са идентификаторите на акаунтите, а стойностите — съ храняваните в акаунтите данни).
Съобщение (message). По-горе използвах израза „кредитиране и дебитиране на средства“ — това е частен пример на съобщение („предаване N грама от акаунта account_1 на акаунт account_2‘). Очевидно, такова съобщение може да изпрати само възел, собственик на частния ключ на акаунта. account_1 — и способен да потвърди това с подпис. Резултатът от доставката на такива съобщения на обикновен акаунт е увеличаване на баланса му, а на смарт договора — изпълнението на кода му (който ще обработи получаването на съобщението). Разбира се, възможни са и други съобщения (предаващи не парични суми, а произволни данни между смарт договорите).
Транзакция (транзакция). Фактът на доставка на съобщение се нарича транзакция. Транзакциите променят състоянието на блокчейна. Именно от транзакциите (записите за доставка на съобщения) се състоят блоковете в блокчейна. В това отношение можем да си представим състоянието на блокчейна като инкрементална база данни — всички блокове са "дифове", които трябва да се приложат последователно, за да получим текущото състояние на базата данни. За конкретиката на опаковането на тези "дифове" (и възстановяването на пълното състояние по тях) ще говорим в следващата статия.
Блокчейн в TON: какво е и за какво служи?
Както беше споменато в предишната статия, блокчейнът е структура от данни, елементите (блоковете) на която са подредени в "верига", и всеки следващ блок в веригата съдържа хеш на предишния. В коментарите беше зададен въпрос: а защо изобщо е необходима такава структура от данни, когато вече имаме DHT — разпределена хеш таблица? Очевидно, че някакви данни могат да се съхраняват и в DHT, но това е подходящо само за не толкова "чувствителна" информация. Балансите на криптовалутата не могат да се съхраняват в DHT — най-вече поради липсата на проверки за цялостност. Всъщност, цялата сложност на структурата на блокчейна нараства в интерес на предотвратяване на намеси в данните, съхранявани в него.
Въпреки това, блокчейнът в TON изглежда още по-сложен от повечето други разпределени системи — и за това има две причини. Първата е стремежът да се минимизира нуждата от форкове. В традиционните криптовалути всички параметри са зададени в началния етап и всяка опит за тяхната промяна води фактически до появата на "алтернативна вселена на криптовалутата". Втората причина е поддръжката на разбиване (шардинг, шардироване) блокчейна. Блокчейн — структура, която не може да намалява с течение на времето; и обикновено всеки възел, отговорен за работата на мрежата, трябва да я съхранява напълно. В традиционните (централизирани) системи за решаване на подобни проблеми се използва шардиринг: част от записите в БД се намира на един сървър, част — на друг и т.н. В случай на криптовалути такава функционалност все още е доста рядка — по-специално, заради трудността да се добави шардиринг в система, където той не е бил планиран първоначално.
Как точно TON планира да реши двете по-горе описани проблеми?
Съдържание на блокчейна. Воркчейни.

Първо, нека говорим за това, какво ще се съхранява в блокчейна. Там ще бъдат съхранени състояния на акаунтите („портфейли“ в основния случай) и смарт-договори (за опростеност ще считаме, че те са същите като акаунтите). По същество това ще бъде обикновена хеш-таблица — ключовете в нея ще бъдат идентификатори, account_id, а стойностите — структури от данни, съдържащи такива неща като:
- баланс;
- код на смарт-договора (единствено за смарт-договори);
- хранилище на данни на смарт-договора (единствено за смарт-договори);
- статистика;
- (по избор) публичен ключ за трансфери от акаунта, по подразбиране account_id;
- опашка от изходящи съобщения (тука те се записват за препращане на получателя);
- списък на последните доставени на този акаунт съобщения.
Както беше споменато по-горе, самите блокове се състоят от транзакции — съобщения, доставени на различни акаунти account_id. Въпреки това, освен account_id, съобщенията съдържат също 32-битово поле workchain_id — идентификатор на т.н. воркчейн (workchain, работещ блокчейн). Това позволява да се имат няколко независими един от друг блокчейна с различни конфигурации. При това workchain_id = 0 се счита за специален случай, нулев воркчейн — именно находящите се в него баланси ще отговарят на криптовалутата TON (Grams). Вероятно, в началото няма да съществуват други воркчейни.
Шардчейни. Infinite Sharding Paradigm.
Но на този растеж на броя блокчейни не спираме. Нека разгледаме шардинга. Представете си, че на всяка сметка (account_id) е присвоен свой собствен блокчейн — в него се съхраняват всички входящи съобщения — а състоянията на всички такива блокчейни се съхраняват на отделни възли.
Разбира се, това е доста разточително: вероятно в всеки от тези шардчейнове (shardchain, shard blockchain) транзакции ще постъпват много рядко и ще са необходими много мощни възли (предварително отбелязвам, че става дума не само за потребители на мобилни телефони — а за сериозни сървъри).
Затова шардчейновете обединяват сметките според двоичните префикси на техните идентификатори: ако шардчейнът има префикс 0110, то в него ще попаднат транзакции на всички account_id, които започват с тези цифри. Този shard_prefix може да има дължина от 0 до 60 бита — и най-важното, че може да се променя динамично.

Както само един от шардчейновете започне да получава прекомерно много транзакции, работещите по него възли по предварително определени правила "разделят" него на две дъщерни — техните префикси ще бъдат с един бит по-дълги (и за единия този бит ще бъде равен на 0, а за другия — 1). Например, shard_prefix = 0110b ще се раздели на 01100b и 01101b. От своя страна, ако два „съседни“ шардчейна започнат да се чувстват достатъчно комфортно (в продължение на известно време), те отново ще се слеят в едно.
Така шардироването се прави „отдолу нагоре“ — предполагаме, че всяка сметка притежава свой шар, но те — за определено време — са „слепени“ по префикси. Това подразбира Infinite Sharding Paradigm (парадигмата на безкрайното шардирование).
Отделно искам да подчертая, че блокчейните съществуват само виртуално — всъщност, workchain_id това е част от идентификатора на конкретен шардчейн. Говорейки формално, всеки шардчейн се определя с двойка числа (workchain_id, shard_prefix).
Корекция на грешки. Вертикални блокчейни.
Традиционно се счита, че всяка транзакция в блокчейна е "изсечена в камък". Въпреки това, в случая с TON е предвидена възможността да „препишем историята“ — ако някой (т.н. възел-„рибак“) ще докаже, че един от блоковете е подписан неправилно. В този случай в съответния шардчейн се добавя специален коригиращ блок, съдържащ хеша на самия коригиран блок (а не на последния блок в шардчейна). Представяйки шардчейн като верига от блокове, подредени по хоризонтал, може да се каже, че коригиращият блок се свързва с грешния блок не вдясно, а отгоре — затова се счита, че той става част от малък „вертикален блокчейн“. По този начин може да се каже, че шардчейните са двумерни блокчейни.

В случай че след грешния блок, на внесените от него промени, са се позовали последващи блокове (т.е. били са извършени нови транзакции на основата на невалидни), към тези блокове също „отгоре“ се добавят коригиращи. Ако блоковете не са засягали „поразената“ информация, на тях тези „коригиращи вълни“ не се разпространяват. Например, в илюстрацията по-горе, транзакцията на първия блок, увеличаваща баланса на сметката C, беше призната за некоректна — затова транзакцията, намаляваща баланса на тази сметка в третия блок, също трябва да бъде анулирана, а над самия блок е записан коригиращ блок.
Трябва да се отбележи — макар че коригиращите блокове се изобразяват разположени „над“ оригиналните, всъщност те ще бъдат добавени в края на съответния блокчейн (там, където би трябвало да се намират хронологически). Двумерното разположение просто показва, към коя точка в блокчейна те ще бъдат „свързани“ (чрез намиращия се в тях хеш на оригиналния блок).
Може да се философства отделно за това, колко добро е решението „да променяме миналото“. Изглежда, че ако допускаме възможността за появата на некоректен блок в шардчейна, не можем да не допуснем и възможността за появата на грешен коригиращ блок. Тук, доколкото мога да съдя, разликата е в броя на възлите, които трябва да постигнат консенсус относно новите блокове — над всеки шардчейн ще работи сравнително малка „работна група“ възли (доста често променящи своя състав), а въвеждането на коригиращи блокове ще изисква съгласието на всички възли-валидатори. Повече за валидаторите, работните групи и другите роли на възлите ще разкажа в следващата статия.
Един блокчейн, за да управлява всички
По-горе е изброена много информация за различните видове блокчейни, която сама по себе си също трябва да се съхранява някъде. По-конкретно, става въпрос за следните данни:
- за количествата и конфигурацията на работните вериги;
- за количествата на шардовете и техните префикси;
- за това, кои възли в момента са отговорни за кои шардове;
- хешове на последно добавените блокове във всички шардове.
Както вече можете да предположите, всички тези неща се записват в още едно хранилище-блокчейн — мастърчейн (masterchain, master blockchain). Поради наличието на хешове от блокове на всички шардове в неговите блокове, той прави системата силно свързана. В това число, това означава, че генерирането на нов блок в мастърчейна ще се извършва непосредствено след генерирането на блокове в шардовете — очаква се блоковете в шардовете да се появяват почти simultaneously на всеки 5 секунди, а следващият блок в мастърчейна — след секунда след това.
Но кой ще бъде отговорен за изпълнението на цялата тази титанична работа — за изпращането на съобщения, изпълнението на смарт контракти, формирането на блоковете в шардовете и мастърчейна, а също така и проверката на блоковете за грешки? Дали всичко това ще се прави на тишина от телефони на милиони потребители с инсталиран клиент на Телеграм? Или може би екипът на Дуров ще се откаже от идеите за децентрализация и това ще се прави от техните сървъри по старомоден начин?
Всъщност, нито един, нито друг отговор не е правилен. Но страниците на тази статия бързо свършват, така че разговорът за различните роли на възлите (вие вече можете да сте забелязали споменавания на някои от тях), а също така и за механиката на тяхната работа ще се проведе в следващата част.
Източник: habr.com
