Howto | Справка

Как мы проектируем лучшую виртуальную машину, чем Ethereum и Eos

IOST 4 октября 2018 г. Новости , ресурсы , технологии Оставить комментарий

Автор Ли Хайфэн — Старший инженер IOST

Бывший старший инженер Tencent и успешный предприниматель. Отвечал за руководство реструктуризацией Tencent News и Tiantian Express, которая привлекла более 150 миллионов посетителей в день. Ведущий инженер виртуальной машины IOST.

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

На прошлой неделе IOST выпустил вторую итерацию нашей тестовой сети — Everest v1.0 . Наряду с поддержкой программирования интеллектуальных контрактов с помощью JavaScript, системы доменных имен с интеллектуальным контактом (DNS) и Multiversion Concurrency Control (MVCC) это обновление также включало развертывание нашей новой виртуальной машины на основе механизма V8.

В следующей технической статье я анализирую и критикую Ethereum и EOS в отношении разработки их виртуальных машин, а также даю обзор вариантов реализации и проектирования IOST, в которых конкретно рассматриваются некоторые из проблем, с которыми сталкиваются сети наших конкурентов.

ВИРТУАЛЬНАЯ МАШИНА ETHEREUM (EVM)

Виртуальная машина Ethereum (EVM) — это «квазитурируемая» 256-битная виртуальная машина, один из важнейших и неотъемлемых компонентов сети Ethereum.

По мере того, как разработка интеллектуальных контрактов EVM постепенно улучшалась, все больше совершенствовались приложения DApp, такие как недавно популярная игра Fomo3D, запущенная в сети.

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

ВО-ПЕРВЫХ, ВИРТУАЛЬНАЯ МАШИНА ETHEREUM (EVM) НЕ ЗАВЕРШЕНА ПО ТЬЮРИНГУ

В настоящее время существует распространенное заблуждение, что виртуальная машина Ethereum завершена по Тьюрингу, однако это не так.

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

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

ВО-ВТОРЫХ, ДИЗАЙН EVM НЕРАЦИОНАЛЬНЫЙ

Поскольку разработка DApp с использованием умных контрактов возросла, постепенно появились некоторые недостатки оригинального дизайна EVM, причем некоторые из них приводили к серьезным проблемам безопасности. Мы считаем, что на виртуальной машине Ethereum существуют следующие проблемы в уровне проектирования и безопасности:

1. УМНЫЙ УРОВЕНЬ ДИЗАЙНА КОНТРАКТА

  • В EVM отсутствует полная поддержка стандартной библиотеки. Даже самая простая поддержка строкового типа, которая очень сложна в EVM, такая как сращивание строк, вырезание, поиск и т. Д., — все должны быть реализованы самими разработчиками. В то же время самореализованная библиотека классов может быть слишком высокой по времени и пространственной сложности, что приводит к потреблению большого количества ненужного газа. В качестве альтернативы разработчик может позаимствовать соответствующий код библиотеки классов из самого проекта с открытым исходным кодом, но это опять-таки создаст дополнительные проблемы безопасности и усложнит аудит кода контракта, что сделает процесс крайне неэффективным.
  • DApps сложно отлаживать и тестировать. В дополнение к исключениям OutOfGas, EVM не возвращает никакой информации разработчику. Невозможно распечатать журналы, сделать точки останова и одношаговую отладку. Хотя механизм событий может частично улучшить проблему, дизайн самого механизма событий определяет, что это не элегантный и простой в использовании инструмент отладки.
  • Числа с плавающей точкой не поддерживаются . Ethereum использует Wei как самую маленькую единицу. Вэй имеет только целые числа и не поддерживает другие гранулярные измерения. Эта конструкция создает проблему точности, вызванную введением чисел с плавающей запятой. Чтобы представить переменную ETH, после переменной будет много нулей, что делает обслуживание кода чрезвычайно сложным. В то же время нельзя отрицать, что числа с плавающей точкой по-прежнему имеют большое значение в определенных сценариях, и от них нельзя отказаться полностью.
  • Контракты не могут быть обновлены. Модернизация контрактов является сильным требованием в умной разработке контрактов Это проблема, которую каждый разработчик контракта должен рассмотреть для своего проекта. Обновления контракта могут реализовывать исправления безопасности для существующих развертываний, а также расширять их удобство использования, функции и многое другое. EVM вообще не поддерживает обновления — что в результате означает, что разработчики могут решить эту проблему только путем заключения новых контрактов — что отнимает много времени, стоит дорого и трудоемко.

2. УМНЫЙ УРОВЕНЬ БЕЗОПАСНОСТИ КОНТРАКТА

  • Проблемы атаки переполнения. Библиотека EVM safeMath не используется по умолчанию. Например, когда разработчик вычисляет солидность uint256 — если конечный результат превышает максимальное значение uint256 — переполнение будет изменено на небольшое число, что создает уязвимость переполнения. Такие токены, как BEC и SMT, пострадали от атак переполнения, которые привели к чрезвычайно серьезным последствиям. Пример уязвимости переполнения в BEC:

  Функция batchTransfer (address [] _receivers, uint256 _value) public, когда NotPaused возвращает (bool) {

  uint cnt = _receivers.length;

  сумма uint256 = сумма uint256 (cnt) * _value;  // здесь произошло переполнение

  require (cnt> 0 && cnt <= 20);

  require (_value> 0 && balances [msg.sender]> = amount);   

 // require всегда устанавливается после переполнения, порождая уязвимость

  balances [msg.sender] = balances [msg.sender] .sub (сумма);

  for (uint i = 0; i <cnt; i ++) {

  balances [_receivers [i]] = balances [_receivers [i]]. add (_value);

  Передача (msg.sender, _receivers [i], _value);

  }

  вернуть истину;

 } 

  • Повторные атаки. Основная особенность надежности заключается в том, что вы можете вызывать другие внешние контракты, но когда вы отправляете ETH на внешний адрес или вызываете внешний контракт, вам необходимо отправить внешний вызов. Если внешний адрес является вредоносным контрактом, злоумышленник может добавить вредоносный код в резервную функцию. Когда происходит такая передача, вызывается резервная функция для выполнения вредоносного кода. Вредоносный код выполняет уязвимую функцию контракта вызова, вызывая повторную передачу передачи. Самая серьезная атака повторного входа произошла в первые дни Ethereum, широко известной уязвимости DAO. Следующий сегмент контракта специально демонстрирует повторную атаку:

 контракт слабых средств управления контентом {сопоставление (адрес => uint);  functiondraw () {// Передача баланса вызывающего абонента и установка карты баланса вызывающего абонента на 0 // Пока невыполненная карта баланса установлена ​​на 0, вы всегда можете вызвать msg.sender для перевода средств и повторно войти сюда ,  if (! msg.sender.call.value (balances [msg.sender]) ()) {throw;  } balances [msg.sender] = 0;  }} контрактная атака {слабый_контракт публичный слабый;  // Это резервная функция.  Он будет срабатывать при переводе внешнего вызова.  Он всегда будет вызывать метод вывода слабого контракта для выполнения повторной атаки.  function () payable {if (weak.balance> = msg.value) {weak.withdraw ();  }}} 

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

  контракт А {

  функция отозвать (uint) возвращает (uint);

 }

 // При выполнении контракта B он будет только проверять, есть ли у контракта A метод возврата, и если так, контракт будет вызван как обычно.

 // Если переданный параметр не имеет метода изъятия, функция обратного вызова A не будет вызвана, что приведет к неожиданному поведению

 контракт B {

  function put (A a) {a.withdraw (42);

 } 

Таким образом, у EVM есть несколько проблем в дизайне и безопасности. Хотя команда EVM разработала новый язык разработки контрактов — Vyper — он все еще находится на экспериментальной стадии и в настоящее время не может использоваться. В настоящее время, когда Ethereum используется в больших масштабах, накопление этих проблем безопасности и проектирования в конечном итоге приведет к серьезным уязвимостям для сети и ее пользователей.

ВИРТУАЛЬНАЯ МАШИНА EOS

EOS — еще одно высококлассное блокчейн-приложение, недавно запущенное и последовавшее по стопам Ethereum. Он имеет собственный набор интеллектуальных контрактных движков, основанных на WebAssembly. Однако в разработке контрактов EOS есть несколько очевидных проблем:

  • Система учетных записей не легко доступна. Для создания новой учетной записи EOS требуется существующая учетная запись, и только после создания учетной записи можно оформить договор. Требование друга или третьего лица с учетной записью EOS является плохим решением и создает барьер для доступа к этой сети. Чтобы создать учетную запись без реферала, вам необходимо сначала приобрести оперативную память, создав еще один финансовый барьер. После создания учетной записи вам необходимо поставить EOS в обмен на время использования ЦП и пропускную способность сети для работы в сети EOS. Эти требования слишком сложны и обременительны для потенциальных разработчиков.
  • Оперативная память стоит дорого. В отличие от пропускной способности и ЦП, в сети EOS нет фиксированного обменного курса для оперативной памяти. Разработчики подвержены риску обменного курса между ОЗУ и EOS и, как правило, не получают обратно то же самое количество токенов, которые они поставили. Это также создает проблему «торговли» ОЗУ — создает возможность для спекуляций, что в свою очередь устраняет предсказуемость затрат для разработчиков.
  • Трудности в развитии. Использование C ++ в качестве языка контрактов значительно увеличивает барьер для разработки контрактов для сообщества разработчиков. Сам по себе C ++ чрезвычайно сложен, и для завершения разработки умного контракта необходимо вызвать API C ++ EOS. В результате, навыки и знания, необходимые для разработки Dapp в сети EOS, достаточно обширны, что приводит к сокращению пула разработчиков, которые могут использовать эту платформу.

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

ВИРТУАЛЬНАЯ МАШИНА IOST

В IOST мы считаем, что успешная виртуальная машина должна обеспечивать простоту использования для разработчиков, обеспечивать надежную безопасность, а также реализовывать элегантный архитектурный дизайн. В этом отношении мы стремились решить иррациональные проблемы проектирования и безопасности, существующие в настоящее время в EVM и EOS. После сравнения преимуществ и недостатков виртуальных машин, таких как EVM, EOS, C Lua, V8 и т. Д., И на основе превосходной производительности V8 для NodeJ и Chrome, мы наконец решили создать виртуальную машину IOST на основе V8.

АРХИТЕКТУРА СИСТЕМЫ IOST VMMANAGER

Ядром архитектуры V8VM является VMManger, который выполняет следующие три функции:

  • ВМ Вход . Он связывает внешние запросы от других модулей, включая запросы RPC, проверку блоков, проверку Tx и т. Д. Работа передается VMWorker после предварительной обработки и форматирования. Это дает единый вход для всех запросов.
  • Управление жизненным циклом VMWorker . Количество рабочих (потоки VMManager) устанавливается динамически в зависимости от нагрузки на систему, что приводит к эффективному повторному использованию. Внутри рабочих горячий запуск JavaScript и сохранение моментальных снимков горячей точки песочницы помогают сократить частое создание виртуальных машин и избежать большой нагрузки на процессор и память при загрузке одного и того же кода. Это увеличит пропускную способность системы, что позволит IOST V8VM достичь высокой производительности даже при обработке контрактов с большими объемами транзакций, таких как fomo3D.
  • Управление интерфейсом с государственной базой данных . Это обеспечивает атомарность (предотвращает частичное обновление базы данных) каждой транзакции IOST, что запрещает всю транзакцию в случае ошибки из-за недостатка средств. В то же время в базе данных состояний создается двухуровневый кеш, а затем сбрасывается в RocksDB . Это обеспечивает меньшее время доступа к различным версиям данных и оптимизированную производительность для временных данных.

Архитектура виртуальной машины IOST

IOST SANDBOX СИСТЕМНАЯ АРХИТЕКТУРА

Как носитель окончательного исполнения смарт-контракта JavaScript, IOST Sandbox завершает вызов V8VM и следующего пакета Chrome V8, который разделен на этапы компиляции и выполнения:

ЭТАП КОМПИЛЯЦИИ

Главным образом для разработки контракта и обмотки, есть две основные функции:

  • Контракт Пакет. Пакетный смарт-контракт, основанный на реализации веб-пакета, упакует весь код JavaScript в рамках текущего контрактного проекта и автоматизирует установку зависимостей, позволяя IOST V8VM разрабатывать крупные контрактные проекты. В то же время модульные системы IOST V8VM и Node.js полностью совместимы и могут беспрепятственно использовать такие методы, как require, module.exports и export, чтобы предоставить разработчикам контрактов собственный опыт разработки JavaScript.
  • Снимок контракта. Благодаря технологии моментальных снимков V8 виртуальная машина IOST повышает производительность, удаляя исходное пустое состояние по умолчанию. Реальная реализация нуждается только в десериализации снимка, чтобы завершить выполнение, значительно улучшая скорость загрузки и скорость выполнения JavaScript.

ВЫПОЛНИТЬ ЭТАП

Для реальной реализации цепного контракта предусмотрены две основные функции:

  • LoadVM . Для завершения инициализации виртуальной машины, включая создание объектов Chrome V8, настройку параметров выполнения системы, импорт связанных библиотек классов JavaScript и т. Д., Завершите тем самым все приготовления перед выполнением интеллектуального контракта. Вот некоторые библиотеки классов JavaScript:
  • Выполнить Окончательная реализация интеллектуального контракта JavaScript на IOST V8VM откроет отдельный контракт на выполнение потоков и будет отслеживать текущее состояние выполнения. Если возникает исключение, использование ресурсов превышает лимит или время исполнения превышает максимальный лимит, будет выполнен вызов Terminate для завершения текущего выполнения контракта, возвращающий результат исключения.

ПРОИЗВОДИТЕЛЬНОСТЬ IOST V8VM

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

Chrome V8 использует JIT, встроенное кеширование и ленивую загрузку для реализации интерпретации JavaScript. Благодаря высокой производительности Chrome V8 скорость выполнения IOST V8VM на JavaScript значительно улучшилась. После тестирования производительности EVM, EOS, C Lua и V8VM в рекурсивных Фибоначчи, копировании памяти и сложных операциях с CPU мы наблюдали следующие результаты:

Эти результаты ясно показали, что IOST V8VM хорошо работает в основных реализациях виртуальных машин. Вышеупомянутый тест содержит время для запуска виртуальной машины и загрузки конфигурации. Видно, что прямая холодная загрузка IOST V8VM также имеет много преимуществ в производительности. Позже мы также присоединимся к пулу объектов ВМ, кэш-памяти LRU и т. Д., Чтобы улучшить использование ЦП и памяти виртуальной машины, чтобы улучшить способность IOST обрабатывать смарт-контракты.

ЗАКЛЮЧЕНИЕ

В настоящее время в нашей тестовой сети запущена первая версия виртуальной машины IOST V8VM. В этой первой версии мы достигли всех предполагаемых функциональных возможностей, а также проверили множество концепций проектирования, таких как голосование, доменное имя контракта, функции токенов и т. Д. В дальнейшем мы продолжим улучшать IOST V8VM со следующими основными целями. :

  • Улучшенная безопасность на всех уровнях и системах
  • Высокая производительность и повышение скорости исполнения контрактов
  • Простота разработки и использования, включая увеличение и улучшение стандартных библиотек
  • Поддержка больших проектов, отладка и полная цепочка инструментов

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

ПРИЛОЖЕНИЕ: ПРОГРАММА ТЕСТИРОВАНИЯ ВИРТУАЛЬНЫХ МАШИН

APPENDIX: VIRTUAL MACHINE BENCHMARK PROGRAM

EVM CODE

 package evm import ( “math/big” “testing” “github.com/ethereum/go-ethereum/accounts/abi/bind” “github.com/ethereum/go-ethereum/accounts/abi/bind/backends” “github.com/ethereum/go-ethereum/common” “github.com/ethereum/go-ethereum/core” “github.com/ethereum/go-ethereum/crypto” ) var bm *Benchmark func init() { key, err := crypto.GenerateKey() auth := bind.NewKeyedTransactor(key) gAlloc := map[common.Address]core.GenesisAccount{ auth.From: {Balance: big.NewInt(1000000)}, } sim := backends.NewSimulatedBackend(gAlloc) _, _, bm, err = DeployBenchmark(auth, sim) if err != nil { panic(err) } sim.Commit() } func BenchmarkFibonacci(b *testing.B) { for i := 0;  i < bN;  i++ { _, err := bm.Fibonacci(nil, big.NewInt(32)) if err != nil { b.Fatalf(“fibonacci run error: %v\n”, err) } } } func BenchmarkStrConcat(b *testing.B) { for i := 0;  i < bN;  i++ { _, err := bm.StrConcat(nil, “This is vm benchmark, tell me who is slower”, big.NewInt(10000)) if err != nil { b.Fatal(err) } } } func BenchmarkCalculate(b *testing.B) { for i := 0;  i < bN;  i++ { _, err := bm.Calculate(nil, big.NewInt(5000)) if err != nil { b.Fatal(err) } } } 

LUA CODE

  function fibonacci(number)

  if number == 0

  then

  return 0

  end

  if number == 1

  then

  return 1

  end

  return fibonacci(number — 1) + fibonacci(number — 2)

 end

 function strConcat(str, cycles)

  local result = “”

  for i = 1, cycles do

  result = result .. str

  end

  return result

 end

 function calculate(cycles)

  local rs = 0

  for i = 0, cycles-1 do

  rs = rs + math.pow(i, 5)

  end

  return rs

 end 

EOS CODE

  class fibonacci : public eosio::contract {

 public:

  using contract::contract;

  /// @abi action

  void calcn(int64_t n) {

  int64_t r = calc(n);

  print(r);

  }

  int calc( int64_t n ) {

  if (n < 0)

  {

  return -1;

  }

  if (n == 0 || n == 1)

  {

  return n;

  }

  return calc(n — 1) + calc(n — 2);

  }

 };

 EOSIO_ABI( fibonacci, (calcn) )

 class stringadd : public eosio::contract {

 public:

  using contract::contract;

  /// @abi action

  void calcn(std::string s, int64_t cycles) {

  std::string ss(s.size() * cycles, ‘\0’);

  int32_t k = 0;

  for (int i = 0; i < cycles; ++i)

  {

  for (int j = 0; j < s.size(); ++j)

  {

  ss[k++] = s[j];

  }

  }

  print(ss);

  }

 };

 EOSIO_ABI( stringadd, (calcn) )

 class calculate : public eosio::contract {

 public:

  using contract::contract;

  /// @abi action

  void calcn(uint64_t cycles) {

  uint64_t rs = 0;

  for (uint64_t i = 0; i < cycles; ++i)

  {

  rs = rs + i * i * i * i * i;

  }

  print(rs);

  }

 };

 EOSIO_ABI( calculate, (calcn) ) 

V8 CODE

  function fibonacci(cycles)

 {

  if (cycles == 0) return 0

  if (cycles == 1) return 1

  return fibonacci(cycles — 1) + fibonacci(cycles — 2)

 }

 function strConcat(str, cycles)

 {

  let rs = »

  for (let i = 0; i < cycles; i++) {

  rs += str

  }

  return rs

 }

 function calculate(cycles)

 {

  let rs = 0

  for (let i = 0; i < cycles; i++) {

  rs = rs + Math.pow(i, 3)

  }

  return rs

 } 

О IOST

IOST строит инфраструктуру блокчейна со сверхвысокими показателями TPS для удовлетворения потребностей децентрализованной экономики в области безопасности и масштабируемости. Наша миссия под руководством команды проверенных основателей и при поддержке инвесторов мирового уровня, включая Sequoia и Matrix Partners, заключается в том, чтобы быть основной архитектурой будущего онлайн-сервисов.

Горизонтальное расширение и высокая пропускная способность достигаются за счет разработки согласованного механизма POB и схемы расширения второго уровня. IOST предоставляет платформу сторонним разработчикам, предпринимателям и предприятиям для реализации ценности за счет повышения производительности транзакций без ущерба для ключевых атрибутов децентрализации: конфиденциальности, открытого участия и защиты сообщества от злонамеренных атак. IOST более децентрализован, чем механизм EOS DPoS, и более масштабируем, чем платформа умных контрактов Ethereum.

IOST.io

FIND US

Twitter: https://twitter.com/BestIost & Telegram channel: https://t.me/iostbest

Bitcointalk forum: https://bitcointalk.org/index.php?topic=5097987.0

We in social media: