fabric-samples/off_chain_data/application-go/parser/blockParser.go
Stanislav Jakuschevskij bd0c03356b
Implement block and transaction processor
Added block processor struct and the process method.
Implemented getting valid transactions from the last processed index.
Added data structures needed for the store.

Decomposed the parser.Block.Transactions() method into readable chunks.

Added transaction processor struct and process method. Unwrapping
read write set data from the transaction, mapping to a new "write"
data structure and passing down to the store.

Store is an empty function and will be implemented next.

Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
2025-02-24 13:14:47 +01:00

104 lines
2.4 KiB
Go

package parser
import (
"fmt"
"offChainData/utils"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
"google.golang.org/protobuf/proto"
)
type Block struct {
block *common.Block
transactions []*Transaction
}
func ParseBlock(block *common.Block) *Block {
return &Block{block, nil}
}
func (b *Block) Number() uint64 {
header := utils.AssertDefined(b.block.GetHeader(), "missing block header")
return header.GetNumber()
}
// TODO: needs cache
func (b *Block) Transactions() []*Transaction {
envelopes := b.unmarshalEnvelopesFromBlockData()
commonPayloads := b.unmarshalPayloadsFrom(envelopes)
payloads := b.parse(commonPayloads)
result := b.createTransactionsFrom(payloads)
return result
}
func (*Block) createTransactionsFrom(payloads []*PayloadImpl) []*Transaction {
result := []*Transaction{}
for _, payload := range payloads {
result = append(result, NewTransaction(payload))
}
return result
}
func (b *Block) parse(commonPayloads []*common.Payload) []*PayloadImpl {
validationCodes := b.extractTransactionValidationCodes()
result := []*PayloadImpl{}
for i, commonPayload := range commonPayloads {
payload := ParsePayload(
commonPayload,
int32(utils.AssertDefined(
validationCodes[i],
fmt.Sprint("missing validation code index", i),
),
),
)
if payload.IsEndorserTransaction() {
result = append(result, payload)
}
}
return result
}
func (*Block) unmarshalPayloadsFrom(envelopes []*common.Envelope) []*common.Payload {
result := []*common.Payload{}
for _, envelope := range envelopes {
commonPayload := &common.Payload{}
if err := proto.Unmarshal(envelope.GetPayload(), commonPayload); err != nil {
panic(err)
}
result = append(result, commonPayload)
}
return result
}
func (b *Block) unmarshalEnvelopesFromBlockData() []*common.Envelope {
result := []*common.Envelope{}
for _, blockData := range b.block.GetData().GetData() {
envelope := &common.Envelope{}
if err := proto.Unmarshal(blockData, envelope); err != nil {
panic(err)
}
result = append(result, envelope)
}
return result
}
func (b *Block) extractTransactionValidationCodes() []byte {
metadata := utils.AssertDefined(
b.block.GetMetadata(),
"missing block metadata",
)
return utils.AssertDefined(
metadata.GetMetadata()[common.BlockMetadataIndex_TRANSACTIONS_FILTER],
"missing transaction validation code",
)
}
// TODO remove unused?
func (b *Block) ToProto() *common.Block {
return b.block
}