Hyperion History API Solution

History API is arguably the most pressing issue on EOS Main Net for a few months now. dApps, block explorers, and wallets must consult historical information to work properly, and running a full history on EOS Main Net became expensive, complex and time-consuming.

V1 History API was deprecated and only a handful of BPs kept providing full public History nodes for the entire network, (kudos to Sw/eden, CryptoLions, EOS Tribe, Greymass, EOS Canada, EOS Asia and Oracle Chain!) while many others are putting considerable efforts on different solutions to solve this problem.

Some argue that this is not a big issue because dApps can find a business model to pay for partial history nodes focused on their transactions, while block explorers and wallets could use light history. However, the prevalent perception among the community is that difficulties in providing historical chain data can hinder EOS capacity to meet scalability expectations, and this kind of prophecy is usually self-fulfilling.

EOS Blockchain contains approximately 46 million blocks at the time of writing (3/7/2019), so for a newcomer to start providing the service, nodes must ingest all those blocks and the 2 more blocks that are appended every second to the blockchain in a process that currently takes weeks. Once synced, the current v1 History Plugin takes more than 5 Tb of storage to run. Querying this database demands lots of processing power and network bandwidth. As a result, running a full history can cost more than USD 15k/month.

A New Perspective

A few months ago EOS Rio team started brainstorming on possible solutions for this issue. Instead of focusing on perceived bottlenecks to increase data ingestion, storage, and querying capabilities, we decided to start from scratch. The first step was to analyze what could be done to optimize database size itself. We learned that History API v1 stores a lot of redundant information.

The original history_plugin bundled with eosio, that provided the v1 API, stored inline action traces nested inside the root actions. This led to an excessive amount of data being stored and transferred whenever a user requested the action history for a given account. Also, inline actions are often used as an “event” mechanism to notify parties on a transaction, and there is little value in storing it.

Hyperion History implements a new approach to data structure and storage:

  1. actions are stored in a flattened format
  2. a parent field is added to the inline actions to point to the parent global sequence
  3. if the inline action data is identical to the parent, it is considered a notification and thus removed from the database
  4. no blocks or transaction data are stored, all information can be reconstructed from actions
  5. no transaction validation information is stored, as all information can be verified on the block information using the Chain API, dApps do not use History for that.

With those changes, the API format focus on delivering shorter response times, lower bandwidth overhead and easier usability for UI/UX developers.

The data structure is stored as follows:

Small but mighty

Changing format and cutting data redundancies reduces database size in about 85%, from almost 5 Tb to approximately 650 Gb. To further improve performance we engineered a multi-threaded indexer that extracts data from the state history plugin and makes it possible to ingest the complete EOS blockchain in approximately 72 hours with proper hardware optimization, while the current solutions can take weeks.

We also introduced an “ABI History Caching Layer” component to prevent deserialization failures when parallel processing historical data over ABI modifications.

For the database, we deployed an Elasticsearch cluster running on two custom assembled bare metal servers collocated on tier 1 infrastructure in Rio de Janeiro/Brazil.

The optimized data structure tends to reduce CPU and bandwidth consumption making infrastructure more scalable. Other BPs running full history APIs are already testing Hyperion and helping on its evolution.

Our very special thanks to Syed Jafri from EOS Cafe that have created a javascript library for Hyperion HTTP API, and already integrated the Hyperion History (v2 API) on bloks.io. Also to the Sw/eden team for working adding v2 compatiblity on cleos. Many thanks also to eosDAC, CryptoLions and BlockMatrix for their contributions.

Suggesting a new History API standard

For developers, delivering a flattened out result is better than today's History API standard. The current eosio history plugin unnecessarily inflates the database with redundant information (for end-user history purposes). The possibility to filter inline actions allowed a reduction on API bandwidth consumption and coding complexity.

To accommodate those changes EOS Rio and other BPs developing history solutions are advocating for a History API V2 standard, to be adopted by the EOS community.

Please take the time to evaluate it and send us feedback.

An Open-Source Project

EOS Rio is already providing History API using Hyperion at https://eos.hyperion.eosrio.io/v2/docs/index.html. The project code and preliminary set up instructions are available at https://github.com/eosrio/Hyperion-History-API, we are releasing this under an open source license for non-commercial use.

We are available to assist anyone who wants to run Hyperion History and we are keen on feedback.

Next Steps

The immediate next step is to implement a WebSocket API for action streaming. That's what we're working now.

When we finish it, the next feature is Hyperion Analytics, an advanced layer on Hyperion History API to offer detailed EOS statistics.

Links

Documentation: https://eos.hyperion.eosrio.io/v2/docs/index.html
Source code: https://github.com/eosrio/Hyperion-History-API
Javascript Library: https://github.com/eoscafe/hyperion-api

Hyperion History API解决方案

. History API可以说是EOS主网上几个月来最紧迫的问题。DApps,块浏览器和钱包必须查阅历史信息才能正常工作,而在EOS主网上运行完整的历史记录变得昂贵,复杂且耗时。

. V1 History API已被弃用,少数BP坚持不断为整个网络提供完整的公共历史节点,(特别感谢Sw / eden,CryptoLions,EOS Tribe,Greymass,EOS Canada,EOS Asia和Oracle Chain!),而其他许多人也都为解决这个问题付出了巨大努力。

. 有些人认为这不是一个大问题,认为DApp可以找到一种商业模式来专门支付于他们交易的部分历史节点,而块浏览器和钱包可以使用光历史。然而,EOS社区普遍认为,提供历史链数据可能会妨碍EOS满足可扩展性预期的能力,而这种预测常常会自己实现。

. 在撰写本文时(2019年3月7日),EOS Blockchain包含大约4600万个块,因此对于新手开始提供服务,节点必须摄取所有这些块以及每秒附加到块链中的另外两个块。目前来看,是一个需要数周的过程。同步后,当前的v1 History Plugin需要超过5 Tb的存储空间才能运行。查询此数据库需要大量处理能力和网络带宽。因此,运行完整的历史记录可能会花费超过15,000美元/月。

一个新视角

. 几个月前,EOS Rio团队开始就此问题的可能性解决方案进行头脑风暴。我们决定从头开始,而不是专注于感知瓶颈以增加数据摄取,存储和查询功能。第一步是分析可以采取哪些措施来优化数据库大小本身。我们了解到History API v1存储了大量冗余信息。

. 原始的history_plugin与eosio捆绑在一起,提供了v1 API,存储了嵌套在根操作中的内联动作跟踪。每当用户请求给定帐户的操作历史时,将导致存储和传输过量数据。此外,内联操作通常用作“事件”机制,以通知交易方,并且存储它几乎没有价值。

. Hyperion History实现了一种新的数据结构和存储方法:

  1. . 动作以展平格式存储。
  2. . 将父字段添加到内联操作以指向父全局序列。
  3. . 如果内联操作数据与父操作数据相同,则将其视为通知,从而从数据库中删除。
  4. . 没有存储块或事务数据,可以从动作重建所有信息。
  5. . 没有存储交易验证信息,因为可以使用Chain API在块信息上验证所有信息,DApp不使用历史记录。
  6. . 通过这些更改,API格式专注于缩短响应时间,降低带宽开销,并使UI / UX开发人员更易于使用。

数据结构存储如下:

小但强大

. 更改格式和减少数据冗余可将数据库大小减少约85%,从近5 Tb减少到约650 Gb。为了进一步提高性能,我们设计了一个多线程索引器,它从状态历史插件中提取数据,并且可以在大约72小时内通过适当的硬件优化来摄取完整的EOS区块链,而当前的解决方案可能需要数周时间。

. 我们还引入了“ABI历史缓存层”组件,以防止在ABI修改上并行处理历史数据时出现反序列化失败。

. 对于数据库,我们部署了一个Elasticsearch集群,该集群在位于巴西里约热内卢的一级基础架构上并置的两个定制组装裸机服务器上运行。

. 优化的数据结构倾向于减少CPU和带宽消耗,使基础架构更具可扩展性。运行完. 整历史API的其他BP已经在测试Hyperion并帮助其发展。

. 我们非常感谢来自EOS Cafe的Syed Jafri为Hyperion HTTP API创建了一个javascript库,并且已经在 bloks.i上集成了Hyperion History(v2 API)。还有Sw / eden团队在cleos上添加v2兼容性。非常感谢eosDAC,CryptoLions和BlockMatrix的贡献。

新history API标准的建议

. 对于开发人员来说,提供扁平的结果优于今天的history API标准。当前的eosio历史插件不必要地使用冗余信息来扩充数据库(用于最终用户历史记录)。过滤内联操作的可能性允许减少API带宽消耗和编码复杂性。

. 为适应这些变化,EOS Rio和其他开发历史解决方案的BP们正在倡导history API V2标准,也终将被EOS 社区采用。

. 请您用一点儿宝贵时间对其进行评估并向我们发送反馈信息。

一个开源项目

. EOS Rio已经在 https://eos.hyperion.eosrio.io/v2/docs/index.html上使用Hyperion提供History API。项目代码和初步设置说明可在 https://github.com/eosrio/Hyperion-History-API获,我们将根据开源许可证发布此用于非商业用途。

我们可以帮助任何想要运行Hyperion History的人,我们期待您的反馈信息。

下一步

下一步是为操作流实现WebSocket API。这就是我们现在正在做的事情。

完成后,下一个功能将实现Hyperion Analytics,这是Hyperion History API上的一个高级层,可提供详细的EOS统计信息。

相关链接

文档链接:https://eos.hyperion.eosrio.io/v2/docs/index.html

源代码链接:https://github.com/eosrio/Hyperion-History-API

Javascript库链接:https://github.com/eoscafe/hyperion-api

Huge thanks to HKEOS for the korean translation :)

히스토리 API는 지난 몇 달간 EOS 메인넷의 가장 시급한 문제였습니다. dApp들, 블록 익스플로러들, 그리고 지갑들은 제대로 작동하기 위해서는 히스토리 정보를 끌어와야 하는데, 풀히스토리 노드를 메인넷에 구축하는 것은 아주 비싸고, 복잡하고 시간이 많이 들게 되었습니다. 첫번째 버전의 히스토리 API는 널리 쓰이지 못했고 오직 몇몇 BP들만 전체 네트워크를 위해 풀 히스토리 노드를 제공했습니다 (Sw/eden, CryptoLions, EOS Tribe, Greymass, EOS Canada, EOS Asia 그리고 Oracle Chain 에게 박수를 보냅니다).

그 동안 다른 BP들은 다른 해결책을 위해 열심히 고민했습니다.

몇몇은 dApp들이 그들의 트랜젝션에만 해당되는 부분적인 히스토리 노드를 돈주고 사용하는 비즈니스 모델을 찾을 수 있기 때문에 이 문제가 중요하지 않다고 주장하기도 합니다. 다른 블록 익스플로러들이나 월렛 또한 라이트 히스토리를 사용할 수 있다고 생각했습니다. 하지만, 커뮤니티에서 대부분 갖고있던 인식은 체인 히스토리 데이터를 제공하는 것의 어려움이 EOS자체의 확장성에 대한 기대를 저버리는 것이며 이런 기대는 대부분 예견된 결과로 이어집니다.

이 글을 쓰는 시점(2019년 3월 7일)에 EOS 블록체인은 대략 4600만 블록을 갖고 있고, 서비스를 제공하기 위해 새로 진입하는 팀의 경우 지금까지 생성된 모든 블록을 소화하며 몇주가 걸리는 작업동안 초당 생성되는 2개의 블록들을 추가로 받아야 합니다. 싱크가 모두 된 다음에는, 버전1의 히스토리 플러그인은 5TB의 스토리지를 잡아먹습니다. 이 데이터베이스를 쿼리하는 것은 수많은 프로세싱 파워와 네트워크 밴드위스를 요구합니다. 결과적으로, 풀히스토리 노드를 운영하는 것은 매 달 15000달러 이상의 비용을 지불해야 합니다.

새로운 관점

몇 달 전 EOS Rio팀은 가능한 솔루션들에 대해 브레인스토밍을 시작했습니다. 이미 인지된 문제점이었던 데이터 인제스천(ingestion), 스토리지, 그리고 쿼리에 집중하기 보다 우리는 문제의 가장 밑장부터 생각해보기로 했습니다. 첫 단계는 데이터베이스 사이즈를 최적화하기 위해 무엇이 필요한지 부터 분석하는 일이었습니다. 우리는 히스토리 API의 버전1이 반복되는 정보를 저장한다는 것을 알았습니다.

버전 1의 API와 함께 제공되었던 기존 eosio의 history_plugin, 루트 액션 안에 있던 인라인 액션 트레이스를 저장했습니다. 이는 상당한 양의 데이터가 저장되어 유저가 어카운트에 대한 액션 히스토리를 요구할 마다 전송되는 결과를 낳았습니다. 또한, 인라인 액션은 주로 “event” 메커니즘으로 트랜젝션 별로 파티들에 노티하는(notify) 용도로 사용되었고, 저장할 가치가 없었습니다.

Hyperion 히스토리는 데이터 스트럭쳐와 스토리지에 새로운 방식으로 접근합니다:

  • 액션들은 보다 가벼운 포맷으로 저장됩니다
  • 패어런트 필드는 패어런트 글로벌 시퀀스에 포인트하기 위한 인라인 액션들에 붙여집니다
  • 인라인 액션 데이터가 패어런트와 동일할 경우, 노티피케이션으로 간주되고 따라서 데이터베이스에서 삭제됩니다
  • 블록 혹은 트랜젝션 데이터는 저장되지 않으며, 모든 정보는 액션으로부터 재건될 있습니다
  • 트랜젝션 벨리데이션 정보는 저장되지 않으며, 따라서 모든 정보는 Chain API 통한 블록 정보를 통해 검증되며, dApp들은 히스토리를 해당 용도로 사용하지 않습니다.

이런 변화들로 인해 API 포맷은 짧은 반응 시간과, 적은 밴드위스 오버해드 그리고 UI/UX 개발자들을 위한 쉬운 사용성을 제공합니다.

데이터 스트럭쳐는 아래와 같습니다:

작지만 강한 솔루션

포맷을 바꾸고 반복되는 데이터를 삭제하여 데이터베이스 사이즈를 85%로 줄일 수 있으며, 5TB에서 650GB로 줄일 수 있습니다. 계속해서 퍼포먼스를 향상시키기 위해 우리는 스테이트 히스토리 플러그인에서 데이터를 가져오는 멀티 쓰레드 인덱서를 만들었고, 지금의 솔루션이 몇 주가 걸렸다면 우리의 솔루션은 약 72시간이라는 시간 안에 적절한 하드웨어 최적화와 함께 EOS 블록체인의 데이터를 모두 인제스트 할 수 있었습니다.

또한 우리는 ABI 변환 중 히스토리 데이터의 병렬 프로세싱 시 역직렬화 오류(deserialization failures)를 방지할 수 있는 “ABI History Caching Layer”도 소개합니다.

데이터베이스를 위해, 우리는 브라질 리우데자네이루의 티어1 인프라와 같은 위치에 있는 두 커스텀 베어메탈 서버로 돌린 Elasticsearch 클러스터를 사용했습니다.

최적화된 데이터 스트럭쳐는 CPU와 밴드위스 사용을 줄이고 인프라 확장성을 확보할 것입니다.

풀 히스토리 노드를 돌리는 다른 BP들은 이미 Hyperion을 테스트하고 발전을 위해 돕고 있습니다.

Hyperion HTTP API를 위해 자바스크립트 라이브러리를 만들고 이미 Hyperion 히스토리 (v2 API) 를 bloks.io 에 적용한 EOS Cafe의 Syed Jafri과 버전2의 cleos호환성을 위해 힘써준 Sw/eden 팀에게 감사의 인사를 전합니다. 또한 많은 도움을 준 eosDAC, CryptoLions 그리고 BlockMatrix 에게도 감사의 인사를 전합니다.

새로운 히스토리 API 기준을 제안합니다

개발자들을 위해, 오늘의 히스토리 API 기준보다 축소된 결과를 제공하는 것이 더 낫다고 생각합니다. 지금의 eosio 히스토리 플러그인은 반복되는 정보 (엔드유저 히스토리를 위해)로 불필요하게 데이터베이스 사이즈를 키웁니다. 인라인 액션을 필터링하는 것은 API 밴드위스 사용과 코딩 복잡성을 줄여주었습니다.

이런 변화들을 수용하기 위해 EOS Rio와 함께 개발한 다른 BP들은 History API V2 standard를 지지하며, EOS 커뮤니티가 이를 채택하기를 바랍니다.

평가와 피드백을 우리와 공유해주시면 감사하겠습니다.

오픈소스 프로젝트

EOS Rio는 Hyperion을 사용해 이미 History API를 제공하고 있습니다 (https://eos.hyperion.eosrio.io/v2/docs/index.html). 프로젝트의 코드와 셋업환경에 대한 인스트럭션은 https://github.com/eosrio/Hyperion-History-API 에서 확인할 수 있습니다. 우리는 이를 비영리 목적인 오픈소스 라이센스로 배포합니다.

또한 우리는 Hyperion 히스토리를 제공하려는 누구든 도움을 줄 수 있으며, 피드백을 기다립니다.

향후 계획

다음 단계는 액션 스트리밍을 위한 WebSocket API를 실행하는 것입니다. 지금 우리가 고민하고 있는 부분입니다. 이 부분이 완료된 후, 다음 피쳐는 Hyperion Analytics 이

며, 이는 보다 디테일한 EOS 통계를 제공하기 위한 Hyperion 히스토리 API 위 추가 레이어입니다.


Made with ❤ by EOS Rio