Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseEnvelope ¶
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
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.