Skip to main content

richat_filter/protobuf/
decode.rs

1use {
2    prost::{
3        DecodeError,
4        bytes::Buf,
5        encoding::{self, DecodeContext, WireType, check_wire_type, decode_key, decode_varint},
6    },
7    prost_types::Timestamp,
8    solana_clock::{Epoch, Slot},
9    solana_pubkey::{PUBKEY_BYTES, Pubkey},
10    solana_signature::SIGNATURE_BYTES,
11    std::{borrow::Cow, collections::HashSet, mem::MaybeUninit, ops::Range},
12};
13
14#[allow(deprecated)]
15fn create_decode_error(description: impl Into<Cow<'static, str>>) -> DecodeError {
16    DecodeError::new(description)
17}
18
19fn decode_error(
20    description: impl Into<Cow<'static, str>>,
21    stack: &[(&'static str, &'static str)],
22) -> DecodeError {
23    let mut error = create_decode_error(description);
24    for (message, field) in stack {
25        error.push(message, field);
26    }
27    error
28}
29
30fn decode_pubkey(
31    buf: &mut impl Buf,
32    wire_type: WireType,
33    struct_name: &'static str,
34    field: &'static str,
35) -> Result<Pubkey, DecodeError> {
36    check_wire_type(WireType::LengthDelimited, wire_type)?;
37    let len = decode_varint(buf)? as usize;
38    if len > buf.remaining() {
39        return Err(decode_error("buffer underflow", &[(struct_name, field)]));
40    }
41    if len != PUBKEY_BYTES {
42        return Err(decode_error(
43            "invalid pubkey length",
44            &[(struct_name, field)],
45        ));
46    }
47    let mut pubkey = MaybeUninit::<[u8; PUBKEY_BYTES]>::uninit();
48    buf.copy_to_slice(unsafe { &mut *pubkey.as_mut_ptr() });
49    Ok(unsafe { pubkey.assume_init() }.into())
50}
51
52pub trait LimitedDecode: Default {
53    fn decode(mut buf: impl Buf) -> Result<Self, DecodeError> {
54        let buf_len = buf.remaining();
55        let mut message = Self::default();
56        while buf.has_remaining() {
57            let (tag, wire_type) = decode_key(&mut buf)?;
58            message.merge_field(tag, wire_type, &mut buf, buf_len)?;
59        }
60        Ok(message)
61    }
62
63    fn merge_field(
64        &mut self,
65        tag: u32,
66        wire_type: WireType,
67        buf: &mut impl Buf,
68        buf_len: usize,
69    ) -> Result<(), DecodeError>;
70}
71
72#[derive(Debug, Default)]
73pub struct SubscribeUpdateLimitedDecode {
74    pub update_oneof: Option<UpdateOneofLimitedDecode>,
75    pub created_at: Option<Timestamp>,
76}
77
78impl LimitedDecode for SubscribeUpdateLimitedDecode {
79    fn merge_field(
80        &mut self,
81        tag: u32,
82        wire_type: WireType,
83        buf: &mut impl Buf,
84        buf_len: usize,
85    ) -> Result<(), DecodeError> {
86        const STRUCT_NAME: &str = "SubscribeUpdateLimitedDecode";
87        check_wire_type(WireType::LengthDelimited, wire_type)?;
88        match tag {
89            1u32 => {
90                let len = decode_varint(buf)? as usize;
91                if len > buf.remaining() {
92                    return Err(decode_error(
93                        "buffer underflow",
94                        &[(STRUCT_NAME, "filters")],
95                    ));
96                }
97                buf.advance(len);
98                Ok(())
99            }
100            #[allow(clippy::manual_range_patterns)]
101            2u32 | 3u32 | 4u32 | 10u32 | 5u32 | 6u32 | 9u32 | 7u32 | 8u32 => {
102                let value = &mut self.update_oneof;
103                UpdateOneofLimitedDecode::merge(value, tag, buf, buf_len).map_err(|mut error| {
104                    error.push(STRUCT_NAME, "update_oneof");
105                    error
106                })
107            }
108            11u32 => {
109                let value = &mut self.created_at;
110                encoding::message::merge(
111                    WireType::LengthDelimited,
112                    value.get_or_insert_with(Default::default),
113                    buf,
114                    DecodeContext::default(),
115                )
116                .map_err(|mut error| {
117                    error.push(STRUCT_NAME, "created_at");
118                    error
119                })
120            }
121            _ => encoding::skip_field(
122                WireType::LengthDelimited,
123                tag,
124                buf,
125                DecodeContext::default(),
126            ),
127        }
128    }
129}
130
131#[derive(Debug)]
132pub enum UpdateOneofLimitedDecode {
133    Account(Range<usize>),
134    Slot(Range<usize>),
135    Transaction(Range<usize>),
136    TransactionStatus(Range<usize>),
137    Block(Range<usize>),
138    Ping(Range<usize>),
139    Pong(Range<usize>),
140    BlockMeta(Range<usize>),
141    Entry(Range<usize>),
142}
143
144impl UpdateOneofLimitedDecode {
145    pub fn merge(
146        field: &mut Option<Self>,
147        tag: u32,
148        buf: &mut impl Buf,
149        buf_len: usize,
150    ) -> Result<(), DecodeError> {
151        let len = decode_varint(buf)? as usize;
152        if len > buf.remaining() {
153            return Err(create_decode_error("buffer underflow"));
154        }
155
156        let start = buf_len - buf.remaining();
157        buf.advance(len);
158        let end = buf_len - buf.remaining();
159        let range = Range { start, end };
160
161        match tag {
162            2u32 => match field {
163                Some(Self::Account(_)) => Err(create_decode_error("merge is not supported")),
164                _ => {
165                    *field = Some(Self::Account(range));
166                    Ok(())
167                }
168            },
169            3u32 => match field {
170                Some(Self::Slot(_)) => Err(create_decode_error("merge is not supported")),
171                _ => {
172                    *field = Some(Self::Slot(range));
173                    Ok(())
174                }
175            },
176            4u32 => match field {
177                Some(Self::Transaction(_)) => Err(create_decode_error("merge is not supported")),
178                _ => {
179                    *field = Some(Self::Transaction(range));
180                    Ok(())
181                }
182            },
183            10u32 => match field {
184                Some(Self::TransactionStatus(_)) => {
185                    Err(create_decode_error("merge is not supported"))
186                }
187                _ => {
188                    *field = Some(Self::TransactionStatus(range));
189                    Ok(())
190                }
191            },
192            5u32 => match field {
193                Some(Self::Block(_)) => Err(create_decode_error("merge is not supported")),
194                _ => {
195                    *field = Some(Self::Block(range));
196                    Ok(())
197                }
198            },
199            6u32 => match field {
200                Some(Self::Ping(_)) => Err(create_decode_error("merge is not supported")),
201                _ => {
202                    *field = Some(Self::Ping(range));
203                    Ok(())
204                }
205            },
206            9u32 => match field {
207                Some(Self::Pong(_)) => Err(create_decode_error("merge is not supported")),
208                _ => {
209                    *field = Some(Self::Pong(range));
210                    Ok(())
211                }
212            },
213            7u32 => match field {
214                Some(Self::BlockMeta(_)) => Err(create_decode_error("merge is not supported")),
215                _ => {
216                    *field = Some(Self::BlockMeta(range));
217                    Ok(())
218                }
219            },
220            8u32 => match field {
221                Some(Self::Entry(_)) => Err(create_decode_error("merge is not supported")),
222                _ => {
223                    *field = Some(Self::Entry(range));
224                    Ok(())
225                }
226            },
227            _ => unreachable!(),
228        }
229    }
230}
231
232#[derive(Debug)]
233pub struct UpdateOneofLimitedDecodeAccount {
234    pub account: usize,
235    pub pubkey: Pubkey,
236    pub owner: Pubkey,
237    pub lamports: u64,
238    pub executable: bool,
239    pub rent_epoch: Epoch,
240    pub data: Range<usize>,
241    pub txn_signature_offset: Option<usize>,
242    pub write_version: usize,
243    pub slot: Slot,
244    pub is_startup: bool,
245}
246
247impl Default for UpdateOneofLimitedDecodeAccount {
248    fn default() -> Self {
249        Self {
250            account: usize::MAX,
251            pubkey: Pubkey::default(),
252            owner: Pubkey::default(),
253            lamports: u64::default(),
254            executable: bool::default(),
255            rent_epoch: Epoch::default(),
256            data: Range::default(),
257            txn_signature_offset: Option::default(),
258            write_version: usize::default(),
259            slot: Slot::default(),
260            is_startup: bool::default(),
261        }
262    }
263}
264
265impl LimitedDecode for UpdateOneofLimitedDecodeAccount {
266    fn merge_field(
267        &mut self,
268        tag: u32,
269        wire_type: WireType,
270        buf: &mut impl Buf,
271        buf_len: usize,
272    ) -> Result<(), DecodeError> {
273        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeAccount";
274        let ctx = DecodeContext::default();
275        match tag {
276            1u32 => {
277                check_wire_type(WireType::LengthDelimited, wire_type)?;
278                self.account = buf_len - buf.remaining();
279                self.account_merge(buf, buf_len).map_err(|mut error| {
280                    error.push(STRUCT_NAME, "account");
281                    error
282                })
283            }
284            2u32 => {
285                let value = &mut self.slot;
286                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
287                    error.push(STRUCT_NAME, "slot");
288                    error
289                })
290            }
291            3u32 => {
292                let value = &mut self.is_startup;
293                encoding::bool::merge(wire_type, value, buf, ctx).map_err(|mut error| {
294                    error.push(STRUCT_NAME, "is_startup");
295                    error
296                })
297            }
298            _ => encoding::skip_field(wire_type, tag, buf, ctx),
299        }
300    }
301}
302
303impl UpdateOneofLimitedDecodeAccount {
304    fn account_merge(&mut self, buf: &mut impl Buf, buf_len: usize) -> Result<(), DecodeError> {
305        let len = decode_varint(buf)?;
306        let remaining = buf.remaining();
307        if len > remaining as u64 {
308            return Err(create_decode_error("buffer underflow"));
309        }
310
311        let limit = remaining - len as usize;
312        while buf.remaining() > limit {
313            let (tag, wire_type) = decode_key(buf)?;
314            self.account_merge_field(tag, wire_type, buf, buf_len)?;
315        }
316
317        if buf.remaining() != limit {
318            return Err(create_decode_error("delimited length exceeded"));
319        }
320        Ok(())
321    }
322
323    fn account_merge_field(
324        &mut self,
325        tag: u32,
326        wire_type: WireType,
327        buf: &mut impl Buf,
328        buf_len: usize,
329    ) -> Result<(), DecodeError> {
330        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeAccount";
331        let ctx = DecodeContext::default();
332        match tag {
333            1u32 => {
334                self.pubkey = decode_pubkey(buf, wire_type, STRUCT_NAME, "pubkey")?;
335                Ok(())
336            }
337            2u32 => {
338                let value = &mut self.lamports;
339                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
340                    error.push(STRUCT_NAME, "lamports");
341                    error
342                })
343            }
344            3u32 => {
345                self.owner = decode_pubkey(buf, wire_type, STRUCT_NAME, "owner")?;
346                Ok(())
347            }
348            4u32 => {
349                let value = &mut self.executable;
350                encoding::bool::merge(wire_type, value, buf, ctx).map_err(|mut error| {
351                    error.push(STRUCT_NAME, "executable");
352                    error
353                })
354            }
355            5u32 => {
356                let value = &mut self.rent_epoch;
357                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
358                    error.push(STRUCT_NAME, "rent_epoch");
359                    error
360                })
361            }
362            6u32 => {
363                check_wire_type(WireType::LengthDelimited, wire_type)?;
364                let len = decode_varint(buf)? as usize;
365                if len > buf.remaining() {
366                    return Err(decode_error("buffer underflow", &[(STRUCT_NAME, "data")]));
367                }
368
369                let start = buf_len - buf.remaining();
370                buf.advance(len);
371                let end = buf_len - buf.remaining();
372                self.data = Range { start, end };
373                Ok(())
374            }
375            7u32 => {
376                self.write_version = buf_len - buf.remaining();
377                let mut value = 0;
378                encoding::uint64::merge(wire_type, &mut value, buf, ctx).map_err(|mut error| {
379                    error.push(STRUCT_NAME, "write_version");
380                    error
381                })
382            }
383            8u32 => {
384                check_wire_type(WireType::LengthDelimited, wire_type)?;
385                let len = decode_varint(buf)? as usize;
386                if len > buf.remaining() {
387                    return Err(decode_error(
388                        "buffer underflow",
389                        &[(STRUCT_NAME, "txn_signature")],
390                    ));
391                }
392                if len != SIGNATURE_BYTES {
393                    return Err(decode_error(
394                        "invalid signature length",
395                        &[(STRUCT_NAME, "txn_signature")],
396                    ));
397                }
398                self.txn_signature_offset = Some(buf_len - buf.remaining());
399                buf.advance(len);
400                Ok(())
401            }
402            _ => encoding::skip_field(wire_type, tag, buf, ctx),
403        }
404    }
405}
406
407#[derive(Debug, Default)]
408pub struct UpdateOneofLimitedDecodeSlot {
409    pub slot: Slot,
410    pub parent: Option<Slot>,
411    pub status: i32,
412    pub dead_error: Option<Range<usize>>,
413}
414
415impl LimitedDecode for UpdateOneofLimitedDecodeSlot {
416    fn merge_field(
417        &mut self,
418        tag: u32,
419        wire_type: WireType,
420        buf: &mut impl Buf,
421        buf_len: usize,
422    ) -> Result<(), DecodeError> {
423        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeSlot";
424        let ctx = DecodeContext::default();
425        match tag {
426            1u32 => {
427                let value = &mut self.slot;
428                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
429                    error.push(STRUCT_NAME, "slot");
430                    error
431                })
432            }
433            2u32 => {
434                let value = &mut self.parent;
435                encoding::uint64::merge(
436                    wire_type,
437                    value.get_or_insert_with(Default::default),
438                    buf,
439                    ctx,
440                )
441                .map_err(|mut error| {
442                    error.push(STRUCT_NAME, "parent");
443                    error
444                })
445            }
446            3u32 => {
447                let value = &mut self.status;
448                encoding::int32::merge(wire_type, value, buf, ctx).map_err(|mut error| {
449                    error.push(STRUCT_NAME, "status");
450                    error
451                })
452            }
453            4u32 => {
454                check_wire_type(WireType::LengthDelimited, wire_type)?;
455                let len = decode_varint(buf)? as usize;
456                if len > buf.remaining() {
457                    return Err(decode_error(
458                        "buffer underflow",
459                        &[(STRUCT_NAME, "dead_error")],
460                    ));
461                }
462
463                let start = buf_len - buf.remaining();
464                buf.advance(len);
465                let end = buf_len - buf.remaining();
466                self.dead_error = Some(Range { start, end });
467                Ok(())
468            }
469            _ => encoding::skip_field(wire_type, tag, buf, ctx),
470        }
471    }
472}
473
474#[derive(Debug, Default)]
475pub struct UpdateOneofLimitedDecodeTransaction {
476    pub transaction: Option<Range<usize>>,
477    pub slot: Slot,
478}
479
480impl LimitedDecode for UpdateOneofLimitedDecodeTransaction {
481    fn merge_field(
482        &mut self,
483        tag: u32,
484        wire_type: WireType,
485        buf: &mut impl Buf,
486        buf_len: usize,
487    ) -> Result<(), DecodeError> {
488        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeTransaction";
489        let ctx = DecodeContext::default();
490        match tag {
491            1u32 => {
492                check_wire_type(WireType::LengthDelimited, wire_type)?;
493                let len = decode_varint(buf)? as usize;
494                if len > buf.remaining() {
495                    return Err(decode_error(
496                        "buffer underflow",
497                        &[(STRUCT_NAME, "transaction")],
498                    ));
499                }
500
501                let start = buf_len - buf.remaining();
502                buf.advance(len);
503                let end = buf_len - buf.remaining();
504                self.transaction = Some(Range { start, end });
505                Ok(())
506            }
507            2u32 => {
508                let value = &mut self.slot;
509                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
510                    error.push(STRUCT_NAME, "slot");
511                    error
512                })
513            }
514            _ => encoding::skip_field(wire_type, tag, buf, ctx),
515        }
516    }
517}
518
519#[derive(Debug, Default)]
520pub struct UpdateOneofLimitedDecodeTransactionInfo {
521    pub signature_offset: Option<usize>,
522    pub is_vote: bool,
523    pub index: u64,
524    pub account_keys: HashSet<Pubkey>,
525    pub err: Option<Range<usize>>,
526}
527
528impl LimitedDecode for UpdateOneofLimitedDecodeTransactionInfo {
529    fn merge_field(
530        &mut self,
531        tag: u32,
532        wire_type: WireType,
533        buf: &mut impl Buf,
534        buf_len: usize,
535    ) -> Result<(), DecodeError> {
536        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeTransactionInfo";
537        let ctx = DecodeContext::default();
538        match tag {
539            1u32 => {
540                // signature
541                check_wire_type(WireType::LengthDelimited, wire_type)?;
542                let len = decode_varint(buf)? as usize;
543                if len > buf.remaining() {
544                    return Err(decode_error(
545                        "buffer underflow",
546                        &[(STRUCT_NAME, "signature")],
547                    ));
548                }
549                if len != SIGNATURE_BYTES {
550                    return Err(decode_error(
551                        "invalid signature length",
552                        &[(STRUCT_NAME, "signature")],
553                    ));
554                }
555                self.signature_offset = Some(buf_len - buf.remaining());
556                buf.advance(len);
557                Ok(())
558            }
559            2u32 => {
560                // is_vote
561                let value = &mut self.is_vote;
562                encoding::bool::merge(wire_type, value, buf, ctx).map_err(|mut error| {
563                    error.push(STRUCT_NAME, "is_vote");
564                    error
565                })
566            }
567            3u32 => {
568                // transaction (nested message containing account_keys)
569                check_wire_type(WireType::LengthDelimited, wire_type)?;
570                self.merge_transaction(buf, buf_len).map_err(|mut error| {
571                    error.push(STRUCT_NAME, "transaction");
572                    error
573                })
574            }
575            4u32 => {
576                // meta (nested message containing loaded addresses and err)
577                check_wire_type(WireType::LengthDelimited, wire_type)?;
578                self.merge_meta(buf, buf_len).map_err(|mut error| {
579                    error.push(STRUCT_NAME, "meta");
580                    error
581                })
582            }
583            5u32 => {
584                // index
585                let value = &mut self.index;
586                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
587                    error.push(STRUCT_NAME, "index");
588                    error
589                })
590            }
591            _ => encoding::skip_field(wire_type, tag, buf, ctx),
592        }
593    }
594}
595
596impl UpdateOneofLimitedDecodeTransactionInfo {
597    fn merge_transaction(&mut self, buf: &mut impl Buf, buf_len: usize) -> Result<(), DecodeError> {
598        let len = decode_varint(buf)?;
599        let remaining = buf.remaining();
600        if len > remaining as u64 {
601            return Err(create_decode_error("buffer underflow"));
602        }
603
604        let limit = remaining - len as usize;
605        while buf.remaining() > limit {
606            let (tag, wire_type) = decode_key(buf)?;
607            // Transaction: message = 2
608            if tag == 2 {
609                check_wire_type(WireType::LengthDelimited, wire_type)?;
610                self.merge_transaction_message(buf, buf_len)?;
611            } else {
612                encoding::skip_field(wire_type, tag, buf, DecodeContext::default())?;
613            }
614        }
615        Ok(())
616    }
617
618    fn merge_transaction_message(
619        &mut self,
620        buf: &mut impl Buf,
621        _buf_len: usize,
622    ) -> Result<(), DecodeError> {
623        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeTransactionInfo";
624        let len = decode_varint(buf)?;
625        let remaining = buf.remaining();
626        if len > remaining as u64 {
627            return Err(create_decode_error("buffer underflow"));
628        }
629
630        let limit = remaining - len as usize;
631        while buf.remaining() > limit {
632            let (tag, wire_type) = decode_key(buf)?;
633            // Message: account_keys = 2
634            if tag == 2 {
635                self.account_keys.insert(decode_pubkey(
636                    buf,
637                    wire_type,
638                    STRUCT_NAME,
639                    "account_keys",
640                )?);
641            } else {
642                encoding::skip_field(wire_type, tag, buf, DecodeContext::default())?;
643            }
644        }
645        Ok(())
646    }
647
648    fn merge_meta(&mut self, buf: &mut impl Buf, buf_len: usize) -> Result<(), DecodeError> {
649        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeTransactionInfo";
650        let len = decode_varint(buf)?;
651        let remaining = buf.remaining();
652        if len > remaining as u64 {
653            return Err(create_decode_error("buffer underflow"));
654        }
655
656        let limit = remaining - len as usize;
657        while buf.remaining() > limit {
658            let (tag, wire_type) = decode_key(buf)?;
659            match tag {
660                1u32 => {
661                    // err
662                    check_wire_type(WireType::LengthDelimited, wire_type)?;
663                    let len = decode_varint(buf)? as usize;
664                    if len > buf.remaining() {
665                        return Err(create_decode_error("buffer underflow"));
666                    }
667                    let start = buf_len - buf.remaining();
668                    buf.advance(len);
669                    let end = buf_len - buf.remaining();
670                    self.err = Some(Range { start, end });
671                }
672                12u32 => {
673                    // loaded_writable_addresses
674                    self.account_keys.insert(decode_pubkey(
675                        buf,
676                        wire_type,
677                        STRUCT_NAME,
678                        "loaded_writable_addresses",
679                    )?);
680                }
681                13u32 => {
682                    // loaded_readonly_addresses
683                    self.account_keys.insert(decode_pubkey(
684                        buf,
685                        wire_type,
686                        STRUCT_NAME,
687                        "loaded_readonly_addresses",
688                    )?);
689                }
690                _ => {
691                    encoding::skip_field(wire_type, tag, buf, DecodeContext::default())?;
692                }
693            }
694        }
695        Ok(())
696    }
697}
698
699#[derive(Debug, Default)]
700pub struct UpdateOneofLimitedDecodeEntry {
701    pub slot: Slot,
702    pub index: u64,
703    pub executed_transaction_count: u64,
704}
705
706impl LimitedDecode for UpdateOneofLimitedDecodeEntry {
707    fn merge_field(
708        &mut self,
709        tag: u32,
710        wire_type: WireType,
711        buf: &mut impl Buf,
712        _buf_len: usize,
713    ) -> Result<(), DecodeError> {
714        const STRUCT_NAME: &str = "UpdateOneofLimitedDecodeEntry";
715        let ctx = DecodeContext::default();
716        match tag {
717            1u32 => {
718                let value = &mut self.slot;
719                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
720                    error.push(STRUCT_NAME, "slot");
721                    error
722                })
723            }
724            2u32 => {
725                let value = &mut self.index;
726                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
727                    error.push(STRUCT_NAME, "index");
728                    error
729                })
730            }
731            3u32 => encoding::uint64::merge(wire_type, &mut 0, buf, ctx).map_err(|mut error| {
732                error.push(STRUCT_NAME, "num_hashes");
733                error
734            }),
735            4u32 => {
736                check_wire_type(WireType::LengthDelimited, wire_type)?;
737                let len = decode_varint(buf)? as usize;
738                if len > buf.remaining() {
739                    Err(create_decode_error("buffer underflow"))
740                } else {
741                    buf.advance(len);
742                    Ok(())
743                }
744            }
745            .map_err(|mut error| {
746                error.push(STRUCT_NAME, "hash");
747                error
748            }),
749            5u32 => {
750                let value = &mut self.executed_transaction_count;
751                encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| {
752                    error.push(STRUCT_NAME, "executed_transaction_count");
753                    error
754                })
755            }
756            6u32 => encoding::uint64::merge(wire_type, &mut 0, buf, ctx).map_err(|mut error| {
757                error.push(STRUCT_NAME, "starting_transaction_index");
758                error
759            }),
760            _ => encoding::skip_field(wire_type, tag, buf, ctx),
761        }
762    }
763}