geyser: include entries to block message (#169)

This commit is contained in:
Kirill Fomichev 2023-08-10 15:39:35 -04:00 committed by GitHub
parent 1e2e3bbba0
commit f2cfba9073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 2237 additions and 409 deletions

View File

@ -16,11 +16,22 @@ The minor version will be incremented upon a breaking change and the patch versi
### Breaking
## 2023-08-10
- @triton-one/yellowstone-grpc:0.2.1
- yellowstone-grpc-client-1.9.0+solana.1.16.1
- yellowstone-grpc-geyser-1.7.0+solana.1.16.1
- yellowstone-grpc-proto-1.9.0+solana.1.16.1
### Features
geyser: include entries to block message ([#169](https://github.com/rpcpool/yellowstone-grpc/pull/169)).
## 2023-07-26
- yellowstone-grpc-geyser-1.6.1+solana.1.16.1
### Fix
### Fixes
geyser: fix config example ([#168](https://github.com/rpcpool/yellowstone-grpc/pull/168)).

8
Cargo.lock generated
View File

@ -4261,7 +4261,7 @@ dependencies = [
[[package]]
name = "yellowstone-grpc-client"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
dependencies = [
"bytes",
"futures",
@ -4275,7 +4275,7 @@ dependencies = [
[[package]]
name = "yellowstone-grpc-client-simple"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
dependencies = [
"anyhow",
"backoff",
@ -4293,7 +4293,7 @@ dependencies = [
[[package]]
name = "yellowstone-grpc-geyser"
version = "1.6.1+solana.1.16.1"
version = "1.7.0+solana.1.16.1"
dependencies = [
"anyhow",
"base64 0.21.2",
@ -4324,7 +4324,7 @@ dependencies = [
[[package]]
name = "yellowstone-grpc-proto"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
dependencies = [
"anyhow",
"prost",

View File

@ -1,9 +1,9 @@
[workspace]
members = [
"examples/rust", # 1.8.0+solana.1.16.1
"yellowstone-grpc-client", # 1.8.0+solana.1.16.1
"yellowstone-grpc-geyser", # 1.6.1+solana.1.16.1
"yellowstone-grpc-proto", # 1.8.0+solana.1.16.1
"examples/rust", # 1.9.0+solana.1.16.1
"yellowstone-grpc-client", # 1.9.0+solana.1.16.1
"yellowstone-grpc-geyser", # 1.7.0+solana.1.16.1
"yellowstone-grpc-proto", # 1.9.0+solana.1.16.1
]
[profile.release]

View File

@ -56,6 +56,7 @@ If all fields are empty then all transactions are broadcasted. Otherwise fields
- `account_include` — filter transactions and accounts which use any of listed accounts
- `include_transactions` — include all transactions
- `include_accounts` — include all accounts updates
- `include_entries` — include all entries
Currently all blocks are broadcasted.

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,12 @@ const _ = grpc.SupportPackageIsVersion7
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GeyserClient interface {
Subscribe(ctx context.Context, opts ...grpc.CallOption) (Geyser_SubscribeClient, error)
Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error)
GetLatestBlockhash(ctx context.Context, in *GetLatestBlockhashRequest, opts ...grpc.CallOption) (*GetLatestBlockhashResponse, error)
GetBlockHeight(ctx context.Context, in *GetBlockHeightRequest, opts ...grpc.CallOption) (*GetBlockHeightResponse, error)
GetSlot(ctx context.Context, in *GetSlotRequest, opts ...grpc.CallOption) (*GetSlotResponse, error)
IsBlockhashValid(ctx context.Context, in *IsBlockhashValidRequest, opts ...grpc.CallOption) (*IsBlockhashValidResponse, error)
GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error)
}
type geyserClient struct {
@ -64,11 +70,71 @@ func (x *geyserSubscribeClient) Recv() (*SubscribeUpdate, error) {
return m, nil
}
func (c *geyserClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) {
out := new(PongResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/Ping", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *geyserClient) GetLatestBlockhash(ctx context.Context, in *GetLatestBlockhashRequest, opts ...grpc.CallOption) (*GetLatestBlockhashResponse, error) {
out := new(GetLatestBlockhashResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/GetLatestBlockhash", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *geyserClient) GetBlockHeight(ctx context.Context, in *GetBlockHeightRequest, opts ...grpc.CallOption) (*GetBlockHeightResponse, error) {
out := new(GetBlockHeightResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/GetBlockHeight", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *geyserClient) GetSlot(ctx context.Context, in *GetSlotRequest, opts ...grpc.CallOption) (*GetSlotResponse, error) {
out := new(GetSlotResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/GetSlot", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *geyserClient) IsBlockhashValid(ctx context.Context, in *IsBlockhashValidRequest, opts ...grpc.CallOption) (*IsBlockhashValidResponse, error) {
out := new(IsBlockhashValidResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/IsBlockhashValid", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *geyserClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) {
out := new(GetVersionResponse)
err := c.cc.Invoke(ctx, "/geyser.Geyser/GetVersion", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// GeyserServer is the server API for Geyser service.
// All implementations must embed UnimplementedGeyserServer
// for forward compatibility
type GeyserServer interface {
Subscribe(Geyser_SubscribeServer) error
Ping(context.Context, *PingRequest) (*PongResponse, error)
GetLatestBlockhash(context.Context, *GetLatestBlockhashRequest) (*GetLatestBlockhashResponse, error)
GetBlockHeight(context.Context, *GetBlockHeightRequest) (*GetBlockHeightResponse, error)
GetSlot(context.Context, *GetSlotRequest) (*GetSlotResponse, error)
IsBlockhashValid(context.Context, *IsBlockhashValidRequest) (*IsBlockhashValidResponse, error)
GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error)
mustEmbedUnimplementedGeyserServer()
}
@ -79,6 +145,24 @@ type UnimplementedGeyserServer struct {
func (UnimplementedGeyserServer) Subscribe(Geyser_SubscribeServer) error {
return status.Errorf(codes.Unimplemented, "method Subscribe not implemented")
}
func (UnimplementedGeyserServer) Ping(context.Context, *PingRequest) (*PongResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
}
func (UnimplementedGeyserServer) GetLatestBlockhash(context.Context, *GetLatestBlockhashRequest) (*GetLatestBlockhashResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetLatestBlockhash not implemented")
}
func (UnimplementedGeyserServer) GetBlockHeight(context.Context, *GetBlockHeightRequest) (*GetBlockHeightResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBlockHeight not implemented")
}
func (UnimplementedGeyserServer) GetSlot(context.Context, *GetSlotRequest) (*GetSlotResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSlot not implemented")
}
func (UnimplementedGeyserServer) IsBlockhashValid(context.Context, *IsBlockhashValidRequest) (*IsBlockhashValidResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsBlockhashValid not implemented")
}
func (UnimplementedGeyserServer) GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented")
}
func (UnimplementedGeyserServer) mustEmbedUnimplementedGeyserServer() {}
// UnsafeGeyserServer may be embedded to opt out of forward compatibility for this service.
@ -118,13 +202,146 @@ func (x *geyserSubscribeServer) Recv() (*SubscribeRequest, error) {
return m, nil
}
func _Geyser_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).Ping(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/Ping",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).Ping(ctx, req.(*PingRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Geyser_GetLatestBlockhash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetLatestBlockhashRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).GetLatestBlockhash(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/GetLatestBlockhash",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).GetLatestBlockhash(ctx, req.(*GetLatestBlockhashRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Geyser_GetBlockHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBlockHeightRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).GetBlockHeight(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/GetBlockHeight",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).GetBlockHeight(ctx, req.(*GetBlockHeightRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Geyser_GetSlot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetSlotRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).GetSlot(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/GetSlot",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).GetSlot(ctx, req.(*GetSlotRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Geyser_IsBlockhashValid_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IsBlockhashValidRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).IsBlockhashValid(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/IsBlockhashValid",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).IsBlockhashValid(ctx, req.(*IsBlockhashValidRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Geyser_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetVersionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GeyserServer).GetVersion(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/geyser.Geyser/GetVersion",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GeyserServer).GetVersion(ctx, req.(*GetVersionRequest))
}
return interceptor(ctx, in, info, handler)
}
// Geyser_ServiceDesc is the grpc.ServiceDesc for Geyser service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Geyser_ServiceDesc = grpc.ServiceDesc{
ServiceName: "geyser.Geyser",
HandlerType: (*GeyserServer)(nil),
Methods: []grpc.MethodDesc{},
Methods: []grpc.MethodDesc{
{
MethodName: "Ping",
Handler: _Geyser_Ping_Handler,
},
{
MethodName: "GetLatestBlockhash",
Handler: _Geyser_GetLatestBlockhash_Handler,
},
{
MethodName: "GetBlockHeight",
Handler: _Geyser_GetBlockHeight_Handler,
},
{
MethodName: "GetSlot",
Handler: _Geyser_GetSlot_Handler,
},
{
MethodName: "IsBlockhashValid",
Handler: _Geyser_IsBlockhashValid_Handler,
},
{
MethodName: "GetVersion",
Handler: _Geyser_GetVersion_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "Subscribe",

View File

@ -1,6 +1,6 @@
[package]
name = "yellowstone-grpc-client-simple"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
authors = ["Triton One"]
edition = "2021"
publish = false

View File

@ -174,6 +174,10 @@ struct ActionSubscribe {
#[clap(long)]
blocks_include_accounts: Option<bool>,
/// Include entries to block message
#[clap(long)]
blocks_include_entries: Option<bool>,
/// Subscribe on block meta updates (without transactions)
#[clap(long)]
blocks_meta: bool,
@ -266,6 +270,7 @@ impl Action {
account_include: args.blocks_account_include.clone(),
include_transactions: args.blocks_include_transactions,
include_accounts: args.blocks_include_accounts,
include_entries: args.blocks_include_entries,
},
);
}

View File

@ -19,7 +19,7 @@
},
"../../yellowstone-grpc-client-nodejs": {
"name": "@triton-one/yellowstone-grpc",
"version": "0.2.0",
"version": "0.2.1",
"license": "Apache-2.0",
"dependencies": {
"@grpc/grpc-js": "^1.8.0"

View File

@ -151,6 +151,7 @@ async function subscribeCommand(client, args) {
accountInclude: args.blocksAccountInclude,
includeTransactions: args.blocksIncludeTransactions,
includeAccounts: args.blocksIncludeAccounts,
includeEntries: args.blocksIncludeEntries,
};
}
@ -328,6 +329,11 @@ function parseCommandLineArgs() {
description: "include accounts to block message",
type: "boolean",
},
"blocks-include-entries": {
default: false,
description: "include entries to block message",
type: "boolean",
},
"blocks-meta": {
default: false,
description: "subscribe on block meta updates (without transactions)",

View File

@ -1,12 +1,12 @@
{
"name": "@triton-one/yellowstone-grpc",
"version": "0.1.5",
"version": "0.2.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@triton-one/yellowstone-grpc",
"version": "0.1.5",
"version": "0.2.1",
"license": "Apache-2.0",
"dependencies": {
"@grpc/grpc-js": "^1.8.0"

View File

@ -1,6 +1,6 @@
{
"name": "@triton-one/yellowstone-grpc",
"version": "0.2.0",
"version": "0.2.1",
"license": "Apache-2.0",
"author": "Triton One",
"description": "Yellowstone gRPC Geyser Node.js Client",

View File

@ -1,6 +1,6 @@
[package]
name = "yellowstone-grpc-client"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
authors = ["Triton One"]
edition = "2021"
description = "Yellowstone gRPC Geyser Simple Client"
@ -16,7 +16,7 @@ http = "0.2.8"
thiserror = "1.0"
tonic = { version = "0.9.2", features = ["gzip", "tls", "tls-roots"] }
tonic-health = "0.9.2"
yellowstone-grpc-proto = { path = "../yellowstone-grpc-proto", version = "1.8.0+solana.1.16.1" }
yellowstone-grpc-proto = { path = "../yellowstone-grpc-proto", version = "1.9.0+solana.1.16.1" }
[dev-dependencies]
tokio = { version = "1.21.2", features = ["macros"] }

View File

@ -1,6 +1,6 @@
[package]
name = "yellowstone-grpc-geyser"
version = "1.6.1+solana.1.16.1"
version = "1.7.0+solana.1.16.1"
authors = ["Triton One"]
edition = "2021"
description = "Yellowstone gRPC Geyser Plugin"

View File

@ -34,7 +34,8 @@
"account_include_any": false,
"account_include_reject": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
"include_transactions": true,
"include_accounts" : false
"include_accounts" : false,
"include_entries" : false
},
"blocks_meta": {
"max": 1

View File

@ -221,6 +221,7 @@ pub struct ConfigGrpcFiltersBlocks {
pub account_include_reject: HashSet<Pubkey>,
pub include_transactions: bool,
pub include_accounts: bool,
pub include_entries: bool,
}
impl Default for ConfigGrpcFiltersBlocks {
@ -232,6 +233,7 @@ impl Default for ConfigGrpcFiltersBlocks {
account_include_reject: HashSet::new(),
include_transactions: true,
include_accounts: true,
include_entries: true,
}
}
}

View File

@ -542,6 +542,7 @@ pub struct FilterBlocksInner {
account_include: HashSet<Pubkey>,
include_transactions: Option<bool>,
include_accounts: Option<bool>,
include_entries: Option<bool>,
}
#[derive(Debug, Default, Clone)]
@ -574,6 +575,10 @@ impl FilterBlocks {
matches!(filter.include_accounts, None | Some(false)) || limit.include_accounts,
"`include_accounts` is not allowed"
);
anyhow::ensure!(
matches!(filter.include_entries, None | Some(false)) || limit.include_accounts,
"`include_entries` is not allowed"
);
this.filters.insert(
name.clone(),
@ -584,6 +589,7 @@ impl FilterBlocks {
)?,
include_transactions: filter.include_transactions,
include_accounts: filter.include_accounts,
include_entries: filter.include_entries,
},
);
}
@ -637,9 +643,15 @@ impl FilterBlocks {
vec![]
};
let entries = if inner.include_entries == Some(true) {
message.entries.iter().collect::<Vec<_>>()
} else {
vec![]
};
(
vec![filter.clone()],
MessageRef::Block((message, transactions, accounts).into()),
MessageRef::Block((message, transactions, accounts, entries).into()),
)
})
.collect()

View File

@ -200,6 +200,18 @@ impl From<&ReplicaEntryInfo<'_>> for MessageEntry {
}
}
impl MessageEntry {
fn to_proto(&self) -> SubscribeUpdateEntry {
SubscribeUpdateEntry {
slot: self.slot,
index: self.index as u64,
num_hashes: self.num_hashes,
hash: self.hash.clone(),
executed_transaction_count: self.executed_transaction_count,
}
}
}
#[derive(Debug, Clone)]
pub struct MessageBlock {
pub parent_slot: u64,
@ -213,6 +225,8 @@ pub struct MessageBlock {
pub transactions: Vec<MessageTransactionInfo>,
pub updated_account_count: u64,
pub accounts: Vec<MessageAccountInfo>,
pub entries_count: u64,
pub entries: Vec<MessageEntry>,
}
impl From<(MessageBlockMeta, Vec<MessageTransactionInfo>)> for MessageBlock {
@ -229,6 +243,8 @@ impl From<(MessageBlockMeta, Vec<MessageTransactionInfo>)> for MessageBlock {
transactions,
updated_account_count: 0,
accounts: Vec::new(),
entries_count: 0,
entries: Vec::new(),
}
}
}
@ -308,6 +324,8 @@ pub struct MessageBlockRef<'a> {
pub transactions: Vec<&'a MessageTransactionInfo>,
pub updated_account_count: u64,
pub accounts: Vec<&'a MessageAccountInfo>,
pub entries_count: u64,
pub entries: Vec<&'a MessageEntry>,
}
impl<'a>
@ -315,13 +333,15 @@ impl<'a>
&'a MessageBlock,
Vec<&'a MessageTransactionInfo>,
Vec<&'a MessageAccountInfo>,
Vec<&'a MessageEntry>,
)> for MessageBlockRef<'a>
{
fn from(
(block, transactions, accounts): (
(block, transactions, accounts, entries): (
&'a MessageBlock,
Vec<&'a MessageTransactionInfo>,
Vec<&'a MessageAccountInfo>,
Vec<&'a MessageEntry>,
),
) -> Self {
Self {
@ -336,6 +356,8 @@ impl<'a>
transactions,
updated_account_count: block.updated_account_count,
accounts,
entries_count: block.entries_count,
entries,
}
}
}
@ -368,13 +390,7 @@ impl<'a> MessageRef<'a> {
transaction: Some(message.transaction.to_proto()),
slot: message.slot,
}),
Self::Entry(message) => UpdateOneof::Entry(SubscribeUpdateEntry {
slot: message.slot,
index: message.index as u64,
num_hashes: message.num_hashes,
hash: message.hash.clone(),
executed_transaction_count: message.executed_transaction_count,
}),
Self::Entry(message) => UpdateOneof::Entry(message.to_proto()),
Self::Block(message) => UpdateOneof::Block(SubscribeUpdateBlock {
slot: message.slot,
blockhash: message.blockhash.clone(),
@ -397,6 +413,12 @@ impl<'a> MessageRef<'a> {
.iter()
.map(|acc| acc.to_proto(accounts_data_slice))
.collect(),
entries_count: message.entries_count,
entries: message
.entries
.iter()
.map(|entry| entry.to_proto())
.collect(),
}),
Self::BlockMeta(message) => UpdateOneof::BlockMeta(SubscribeUpdateBlockMeta {
slot: message.slot,
@ -731,10 +753,18 @@ impl GrpcService {
accounts.push(account.account.clone());
}
}
block.updated_account_count = accounts.len() as u64;
block.accounts = accounts;
let mut entries = Vec::with_capacity(vec.len());
for item in vec {
if let Some(Message::Entry(entry)) = item {
entries.push(entry.clone());
}
}
block.entries_count = entries.len() as u64;
block.entries = entries;
*collected = true;
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "yellowstone-grpc-proto"
version = "1.8.0+solana.1.16.1"
version = "1.9.0+solana.1.16.1"
authors = ["Triton One"]
edition = "2021"
description = "Yellowstone gRPC Geyser Protobuf Definitions"

View File

@ -71,6 +71,7 @@ message SubscribeRequestFilterBlocks {
repeated string account_include = 1;
optional bool include_transactions = 2;
optional bool include_accounts = 3;
optional bool include_entries = 4;
}
message SubscribeRequestFilterBlocksMeta {}
@ -143,6 +144,8 @@ message SubscribeUpdateBlock {
repeated SubscribeUpdateTransactionInfo transactions = 6;
uint64 updated_account_count = 10;
repeated SubscribeUpdateAccountInfo accounts = 11;
uint64 entries_count = 12;
repeated SubscribeUpdateEntry entries = 13;
}
message SubscribeUpdateBlockMeta {