serialization

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseEnvelope

func ParseEnvelope(envelope *common.Envelope) (*common.Payload, *common.ChannelHeader, error)

ParseEnvelope parse the envelope content.

func UnmarshalTx

func UnmarshalTx(data []byte) (*applicationpb.Tx, error)

UnmarshalTx unmarshal data bytes to protoblocktx.Tx.

func UnwrapEnvelope

func UnwrapEnvelope(message []byte) ([]byte, *common.ChannelHeader, error)

UnwrapEnvelope deserialize an envelope.

Types

type EnvelopeLite added in v0.2.0

type EnvelopeLite struct {
	HeaderType int32
	TxID       string
	Data       []byte
}

EnvelopeLite holds the minimal fields extracted from a protobuf Envelope.

func UnwrapEnvelopeLite added in v0.2.0

func UnwrapEnvelopeLite(message []byte) (*EnvelopeLite, error)

UnwrapEnvelopeLite extracts HeaderType, TxID, and payload Data from a serialized Envelope by walking the protobuf wire format directly, instead of performing 3 chained proto.Unmarshal calls (Envelope → Payload → ChannelHeader) like UnwrapEnvelope does. This reduces allocations and improves performance.

The orderer already validates envelope structure (channelHeader, signatureHeader) before including transactions in a block, so the committer only receives valid envelopes. The only scenario where malformed envelopes could arrive is if BFT consensus itself is compromised (more than f malicious nodes), at which point the system has already failed. Therefore, this function only needs to handle well-formed input correctly and does not attempt to match proto.Unmarshal's error behavior on malformed input.

The function navigates through the following nested proto messages, extracting only the fields it needs (marked with ←) and skipping the rest:

message Envelope {
    bytes payload = 1;   // serialized Payload
    bytes signature = 2;
}

message Payload {
    Header header = 1;   // serialized Header
    bytes data = 2;      // ← EnvelopeLite.Data
}

message Header {
    bytes channel_header = 1;   // serialized ChannelHeader
    bytes signature_header = 2;
}

message ChannelHeader {
    int32 type = 1;                          // ← EnvelopeLite.HeaderType
    int32 version = 2;
    google.protobuf.Timestamp timestamp = 3;
    string channel_id = 4;
    string tx_id = 5;                        // ← EnvelopeLite.TxID
    uint64 epoch = 6;
    bytes extension = 7;
    bytes tls_cert_hash = 8;
}

Each protobuf field is encoded on the wire as:

[tag] [value]

The tag is a varint encoding (field_number << 3 | wire_type).

For bytes/string fields, the value is a length prefix followed by the raw bytes:

[tag: 1 byte] [length: varint] [data: length bytes]

For varint fields (like int32), the value is just the varint itself:

[tag: 1 byte] [value: varint]

For example, an Envelope with Type=3 (ENDORSER_TRANSACTION), TxID="tx1", and Data="hello" encodes as:

Envelope (20 bytes):
  0a    = tag: field_number=1, wire_type=2 (bytes)   [1<<3|2 = 0x0a]
  12    = length: 18 bytes
  [...] = Payload (serialized, 18 bytes)             → Envelope.payload

  Payload (18 bytes, nested inside Envelope):
    0a    = tag: field_number=1, wire_type=2 (bytes) [1<<3|2 = 0x0a]
    09    = length: 9 bytes
    [...] = Header (serialized, 9 bytes)             → Payload.header

    12    = tag: field_number=2, wire_type=2 (bytes) [2<<3|2 = 0x12]
    05    = length: 5 bytes
    68656c6c6f = "hello"                             → Payload.data ←

    Header (9 bytes, nested inside Payload):
      0a    = tag: field_number=1, wire_type=2 (bytes) [1<<3|2 = 0x0a]
      07    = length: 7 bytes
      [...] = ChannelHeader (serialized, 7 bytes)      → Header.channel_header

      ChannelHeader (7 bytes, nested inside Header):
        08  = tag: field_number=1, wire_type=0 (varint) [1<<3|0 = 0x08]
        03  = value: 3 (ENDORSER_TRANSACTION)           → ChannelHeader.type ←

        2a  = tag: field_number=5, wire_type=2 (bytes)  [5<<3|2 = 0x2a]
        03  = length: 3 bytes
        747831 = "tx1"                                  → ChannelHeader.tx_id ←

The function reads tags sequentially at each nesting level using protowire, returning immediately when the target field is found and skipping everything before it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL