mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-18 07:55:10 +00:00
Refactor parser package, decompose files
Every struct was put in its own file. Every method which is not used outside the parser package was given package scope. All interfaces were removed, they are implemented by the structs which are now used everywhere needed as return values. There is no clear benefit of using interfaces in this sample. Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
This commit is contained in:
parent
624f65da12
commit
81efd2cc61
11 changed files with 204 additions and 305 deletions
|
|
@ -58,11 +58,11 @@ func (*Block) unmarshalPayloadsFrom(envelopes []*common.Envelope) []*common.Payl
|
|||
return result
|
||||
}
|
||||
|
||||
func (b *Block) parse(commonPayloads []*common.Payload) []*PayloadImpl {
|
||||
func (b *Block) parse(commonPayloads []*common.Payload) []*payload {
|
||||
validationCodes := b.extractTransactionValidationCodes()
|
||||
result := []*PayloadImpl{}
|
||||
result := []*payload{}
|
||||
for i, commonPayload := range commonPayloads {
|
||||
payload := ParsePayload(
|
||||
payload := parsePayload(
|
||||
commonPayload,
|
||||
int32(utils.AssertDefined(
|
||||
validationCodes[i],
|
||||
|
|
@ -70,7 +70,7 @@ func (b *Block) parse(commonPayloads []*common.Payload) []*PayloadImpl {
|
|||
),
|
||||
),
|
||||
)
|
||||
if payload.IsEndorserTransaction() {
|
||||
if payload.isEndorserTransaction() {
|
||||
result = append(result, payload)
|
||||
}
|
||||
}
|
||||
|
|
@ -89,15 +89,10 @@ func (b *Block) extractTransactionValidationCodes() []byte {
|
|||
)
|
||||
}
|
||||
|
||||
func (*Block) createTransactionsFrom(payloads []*PayloadImpl) []*Transaction {
|
||||
func (*Block) createTransactionsFrom(payloads []*payload) []*Transaction {
|
||||
result := []*Transaction{}
|
||||
for _, payload := range payloads {
|
||||
result = append(result, NewTransaction(payload))
|
||||
result = append(result, newTransaction(payload))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO remove unused?
|
||||
func (b *Block) ToProto() *common.Block {
|
||||
return b.block
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
package parser_test
|
||||
package parser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
atb "offChainData/contract"
|
||||
"offChainData/parser"
|
||||
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
||||
|
|
@ -35,13 +34,13 @@ func Test_GetReadWriteSetsFromEndorserTransaction(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
parsedEndorserTransaction := parser.ParseEndorserTransaction(transaction)
|
||||
if len(parsedEndorserTransaction.ReadWriteSets()) != 1 {
|
||||
t.Fatal("expected 1 ReadWriteSet, got", len(parsedEndorserTransaction.ReadWriteSets()))
|
||||
parsedEndorserTransaction := parseEndorserTransaction(transaction)
|
||||
if len(parsedEndorserTransaction.readWriteSets()) != 1 {
|
||||
t.Fatal("expected 1 ReadWriteSet, got", len(parsedEndorserTransaction.readWriteSets()))
|
||||
}
|
||||
|
||||
assertReadWriteSet(
|
||||
parsedEndorserTransaction.ReadWriteSets()[0].NamespaceReadWriteSets()[0],
|
||||
parsedEndorserTransaction.readWriteSets()[0].namespaceReadWriteSets()[0],
|
||||
expectedNamespace,
|
||||
expectedAsset,
|
||||
t,
|
||||
|
|
@ -49,7 +48,7 @@ func Test_GetReadWriteSetsFromEndorserTransaction(t *testing.T) {
|
|||
}
|
||||
|
||||
func assertReadWriteSet(
|
||||
parsedNsRwSet parser.NamespaceReadWriteSet,
|
||||
parsedNsRwSet *NamespaceReadWriteSet,
|
||||
expectedNamespace string,
|
||||
expectedAsset atb.Asset,
|
||||
t *testing.T,
|
||||
|
|
@ -80,16 +79,16 @@ func Test_ReadWriteSetWrapping(t *testing.T) {
|
|||
NsRwset: []*rwset.NsReadWriteSet{nsReadWriteSetFake},
|
||||
}
|
||||
|
||||
parsedRwSet := parser.ParseReadWriteSet(txReadWriteSetFake)
|
||||
if len(parsedRwSet.NamespaceReadWriteSets()) != 1 {
|
||||
t.Fatalf("Expected 1 NamespaceReadWriteSet, got %d", len(parsedRwSet.NamespaceReadWriteSets()))
|
||||
parsedRwSet := parseReadWriteSet(txReadWriteSetFake)
|
||||
if len(parsedRwSet.namespaceReadWriteSets()) != 1 {
|
||||
t.Fatalf("Expected 1 NamespaceReadWriteSet, got %d", len(parsedRwSet.namespaceReadWriteSets()))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NamespaceReadWriteSetParsing(t *testing.T) {
|
||||
nsReadWriteSetFake, expectedNamespace, expectedAsset := nsReadWriteSetFake()
|
||||
|
||||
parsedNsRwSet := parser.ParseNamespaceReadWriteSet(nsReadWriteSetFake)
|
||||
parsedNsRwSet := parseNamespaceReadWriteSet(nsReadWriteSetFake)
|
||||
assertReadWriteSet(
|
||||
parsedNsRwSet,
|
||||
expectedNamespace,
|
||||
|
|
|
|||
105
off_chain_data/application-go/parser/endorserTransaction.go
Normal file
105
off_chain_data/application-go/parser/endorserTransaction.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"offChainData/utils"
|
||||
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type endorserTransaction struct {
|
||||
transaction *peer.Transaction
|
||||
}
|
||||
|
||||
func parseEndorserTransaction(transaction *peer.Transaction) *endorserTransaction {
|
||||
return &endorserTransaction{transaction}
|
||||
}
|
||||
|
||||
func (p *endorserTransaction) readWriteSets() []*readWriteSet {
|
||||
return utils.Cache(func() []*readWriteSet {
|
||||
chaincodeActionPayloads := p.unmarshalChaincodeActionPayloads()
|
||||
|
||||
chaincodeEndorsedActions := p.extractChaincodeEndorsedActionsFrom(chaincodeActionPayloads)
|
||||
|
||||
proposalResponsePayloads := p.unmarshalProposalResponsePayloadsFrom(chaincodeEndorsedActions)
|
||||
|
||||
chaincodeActions := p.unmarshalChaincodeActionsFrom(proposalResponsePayloads)
|
||||
|
||||
txReadWriteSets := p.unmarshalTxReadWriteSetsFrom(chaincodeActions)
|
||||
|
||||
return p.parseReadWriteSets(txReadWriteSets)
|
||||
})()
|
||||
}
|
||||
|
||||
func (p *endorserTransaction) unmarshalChaincodeActionPayloads() []*peer.ChaincodeActionPayload {
|
||||
result := []*peer.ChaincodeActionPayload{}
|
||||
for _, transactionAction := range p.transaction.GetActions() {
|
||||
chaincodeActionPayload := &peer.ChaincodeActionPayload{}
|
||||
if err := proto.Unmarshal(transactionAction.GetPayload(), chaincodeActionPayload); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result = append(result, chaincodeActionPayload)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*endorserTransaction) extractChaincodeEndorsedActionsFrom(chaincodeActionPayloads []*peer.ChaincodeActionPayload) []*peer.ChaincodeEndorsedAction {
|
||||
result := []*peer.ChaincodeEndorsedAction{}
|
||||
for _, payload := range chaincodeActionPayloads {
|
||||
result = append(
|
||||
result,
|
||||
utils.AssertDefined(
|
||||
payload.GetAction(),
|
||||
"missing chaincode endorsed action",
|
||||
),
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*endorserTransaction) unmarshalProposalResponsePayloadsFrom(chaincodeEndorsedActions []*peer.ChaincodeEndorsedAction) []*peer.ProposalResponsePayload {
|
||||
result := []*peer.ProposalResponsePayload{}
|
||||
for _, endorsedAction := range chaincodeEndorsedActions {
|
||||
proposalResponsePayload := &peer.ProposalResponsePayload{}
|
||||
if err := proto.Unmarshal(endorsedAction.GetProposalResponsePayload(), proposalResponsePayload); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result = append(result, proposalResponsePayload)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*endorserTransaction) unmarshalChaincodeActionsFrom(proposalResponsePayloads []*peer.ProposalResponsePayload) []*peer.ChaincodeAction {
|
||||
result := []*peer.ChaincodeAction{}
|
||||
for _, proposalResponsePayload := range proposalResponsePayloads {
|
||||
chaincodeAction := &peer.ChaincodeAction{}
|
||||
if err := proto.Unmarshal(proposalResponsePayload.GetExtension(), chaincodeAction); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result = append(result, chaincodeAction)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*endorserTransaction) unmarshalTxReadWriteSetsFrom(chaincodeActions []*peer.ChaincodeAction) []*rwset.TxReadWriteSet {
|
||||
result := []*rwset.TxReadWriteSet{}
|
||||
for _, chaincodeAction := range chaincodeActions {
|
||||
txReadWriteSet := &rwset.TxReadWriteSet{}
|
||||
if err := proto.Unmarshal(chaincodeAction.GetResults(), txReadWriteSet); err != nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, txReadWriteSet)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*endorserTransaction) parseReadWriteSets(txReadWriteSets []*rwset.TxReadWriteSet) []*readWriteSet {
|
||||
result := []*readWriteSet{}
|
||||
for _, txReadWriteSet := range txReadWriteSets {
|
||||
parsedReadWriteSet := parseReadWriteSet(txReadWriteSet)
|
||||
result = append(result, parsedReadWriteSet)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package parser
|
||||
|
||||
import "github.com/hyperledger/fabric-protos-go-apiv2/msp"
|
||||
|
||||
// Implements identity.Identity Interface
|
||||
type identityImpl struct {
|
||||
creator *msp.SerializedIdentity
|
||||
}
|
||||
|
||||
func (i *identityImpl) MspID() string {
|
||||
return i.creator.GetMspid()
|
||||
}
|
||||
|
||||
func (i *identityImpl) Credentials() []byte {
|
||||
return i.creator.GetIdBytes()
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"offChainData/utils"
|
||||
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type NamespaceReadWriteSet struct {
|
||||
nsReadWriteSet *rwset.NsReadWriteSet
|
||||
}
|
||||
|
||||
func parseNamespaceReadWriteSet(nsRwSet *rwset.NsReadWriteSet) *NamespaceReadWriteSet {
|
||||
return &NamespaceReadWriteSet{nsRwSet}
|
||||
}
|
||||
|
||||
func (p *NamespaceReadWriteSet) Namespace() string {
|
||||
return p.nsReadWriteSet.GetNamespace()
|
||||
}
|
||||
|
||||
func (p *NamespaceReadWriteSet) ReadWriteSet() *kvrwset.KVRWSet {
|
||||
return utils.Cache(func() *kvrwset.KVRWSet {
|
||||
result := kvrwset.KVRWSet{}
|
||||
if err := proto.Unmarshal(p.nsReadWriteSet.GetRwset(), &result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &result
|
||||
})()
|
||||
}
|
||||
|
|
@ -9,29 +9,18 @@ import (
|
|||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// TODO remove interface, use struct; encapsulate
|
||||
type Payload interface {
|
||||
ChannelHeader() *common.ChannelHeader
|
||||
EndorserTransaction() EndorserTransaction
|
||||
SignatureHeader() *common.SignatureHeader
|
||||
TransactionValidationCode() int32
|
||||
IsEndorserTransaction() bool
|
||||
IsValid() bool
|
||||
ToProto() *common.Payload
|
||||
type payload struct {
|
||||
commonPayload *common.Payload
|
||||
statusCode int32
|
||||
}
|
||||
|
||||
type PayloadImpl struct {
|
||||
payload *common.Payload
|
||||
statusCode int32
|
||||
func parsePayload(commonPayload *common.Payload, statusCode int32) *payload {
|
||||
return &payload{commonPayload, statusCode}
|
||||
}
|
||||
|
||||
func ParsePayload(payload *common.Payload, statusCode int32) *PayloadImpl {
|
||||
return &PayloadImpl{payload, statusCode}
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) ChannelHeader() *common.ChannelHeader {
|
||||
func (p *payload) channelHeader() *common.ChannelHeader {
|
||||
return utils.Cache(func() *common.ChannelHeader {
|
||||
header := utils.AssertDefined(p.payload.GetHeader(), "missing payload header")
|
||||
header := utils.AssertDefined(p.commonPayload.GetHeader(), "missing payload header")
|
||||
|
||||
result := &common.ChannelHeader{}
|
||||
if err := proto.Unmarshal(header.GetChannelHeader(), result); err != nil {
|
||||
|
|
@ -42,45 +31,23 @@ func (p *PayloadImpl) ChannelHeader() *common.ChannelHeader {
|
|||
})()
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) EndorserTransaction() EndorserTransaction {
|
||||
if !p.IsEndorserTransaction() {
|
||||
panic(fmt.Errorf("unexpected payload type: %d", p.ChannelHeader().GetType()))
|
||||
func (p *payload) endorserTransaction() *endorserTransaction {
|
||||
if !p.isEndorserTransaction() {
|
||||
panic(fmt.Errorf("unexpected payload type: %d", p.channelHeader().GetType()))
|
||||
}
|
||||
|
||||
result := &peer.Transaction{}
|
||||
if err := proto.Unmarshal(p.payload.GetData(), result); err != nil {
|
||||
if err := proto.Unmarshal(p.commonPayload.GetData(), result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ParseEndorserTransaction(result)
|
||||
return parseEndorserTransaction(result)
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) SignatureHeader() *common.SignatureHeader {
|
||||
return utils.Cache(func() *common.SignatureHeader {
|
||||
header := utils.AssertDefined(p.payload.GetHeader(), "missing payload header")
|
||||
|
||||
result := &common.SignatureHeader{}
|
||||
if err := proto.Unmarshal(header.GetSignatureHeader(), result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return result
|
||||
})()
|
||||
func (p *payload) isEndorserTransaction() bool {
|
||||
return p.channelHeader().GetType() == int32(common.HeaderType_ENDORSER_TRANSACTION)
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) TransactionValidationCode() int32 {
|
||||
return p.statusCode
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) IsEndorserTransaction() bool {
|
||||
return p.ChannelHeader().GetType() == int32(common.HeaderType_ENDORSER_TRANSACTION)
|
||||
}
|
||||
|
||||
func (p *PayloadImpl) IsValid() bool {
|
||||
func (p *payload) isValid() bool {
|
||||
return p.statusCode == int32(peer.TxValidationCode_VALID)
|
||||
}
|
||||
|
||||
// TODO remove unused
|
||||
func (p *PayloadImpl) ToProto() *common.Payload {
|
||||
return p.payload
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,72 +1,22 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"offChainData/utils"
|
||||
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// TODO remove interface, use struct; encapsulate; extract into file
|
||||
type ReadWriteSet interface {
|
||||
NamespaceReadWriteSets() []NamespaceReadWriteSet
|
||||
ToProto() *rwset.TxReadWriteSet
|
||||
}
|
||||
|
||||
type ReadWriteSetImpl struct {
|
||||
type readWriteSet struct {
|
||||
readWriteSet *rwset.TxReadWriteSet
|
||||
}
|
||||
|
||||
func ParseReadWriteSet(rwSet *rwset.TxReadWriteSet) *ReadWriteSetImpl {
|
||||
return &ReadWriteSetImpl{rwSet}
|
||||
func parseReadWriteSet(rwSet *rwset.TxReadWriteSet) *readWriteSet {
|
||||
return &readWriteSet{rwSet}
|
||||
}
|
||||
|
||||
func (p *ReadWriteSetImpl) NamespaceReadWriteSets() []NamespaceReadWriteSet {
|
||||
result := []NamespaceReadWriteSet{}
|
||||
func (p *readWriteSet) namespaceReadWriteSets() []*NamespaceReadWriteSet {
|
||||
result := []*NamespaceReadWriteSet{}
|
||||
for _, nsReadWriteSet := range p.readWriteSet.GetNsRwset() {
|
||||
parsedNamespaceReadWriteSet := ParseNamespaceReadWriteSet(nsReadWriteSet)
|
||||
parsedNamespaceReadWriteSet := parseNamespaceReadWriteSet(nsReadWriteSet)
|
||||
result = append(result, parsedNamespaceReadWriteSet)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO remove unused
|
||||
func (p *ReadWriteSetImpl) ToProto() *rwset.TxReadWriteSet {
|
||||
return p.readWriteSet
|
||||
}
|
||||
|
||||
// TODO remove interface, use struct
|
||||
type NamespaceReadWriteSet interface {
|
||||
Namespace() string
|
||||
ReadWriteSet() *kvrwset.KVRWSet
|
||||
ToProto() *rwset.NsReadWriteSet
|
||||
}
|
||||
|
||||
type NamespaceReadWriteSetImpl struct {
|
||||
nsReadWriteSet *rwset.NsReadWriteSet
|
||||
}
|
||||
|
||||
func ParseNamespaceReadWriteSet(nsRwSet *rwset.NsReadWriteSet) *NamespaceReadWriteSetImpl {
|
||||
return &NamespaceReadWriteSetImpl{nsRwSet}
|
||||
}
|
||||
|
||||
func (p *NamespaceReadWriteSetImpl) Namespace() string {
|
||||
return p.nsReadWriteSet.GetNamespace()
|
||||
}
|
||||
|
||||
func (p *NamespaceReadWriteSetImpl) ReadWriteSet() *kvrwset.KVRWSet {
|
||||
return utils.Cache(func() *kvrwset.KVRWSet {
|
||||
result := kvrwset.KVRWSet{}
|
||||
if err := proto.Unmarshal(p.nsReadWriteSet.GetRwset(), &result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &result
|
||||
})()
|
||||
}
|
||||
|
||||
// TODO remove unused
|
||||
func (p *NamespaceReadWriteSetImpl) ToProto() *rwset.NsReadWriteSet {
|
||||
return p.nsReadWriteSet
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,165 +1,30 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"offChainData/utils"
|
||||
|
||||
"github.com/hyperledger/fabric-gateway/pkg/identity"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/common"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/msp"
|
||||
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type Transaction struct {
|
||||
payload Payload
|
||||
payload *payload
|
||||
}
|
||||
|
||||
func NewTransaction(payload Payload) *Transaction {
|
||||
func newTransaction(payload *payload) *Transaction {
|
||||
return &Transaction{payload}
|
||||
}
|
||||
|
||||
func (t *Transaction) ChannelHeader() *common.ChannelHeader {
|
||||
return t.payload.ChannelHeader()
|
||||
return t.payload.channelHeader()
|
||||
}
|
||||
|
||||
// TODO remove unused?
|
||||
func (t *Transaction) Creator() identity.Identity {
|
||||
creator := &msp.SerializedIdentity{}
|
||||
if err := proto.Unmarshal(t.payload.SignatureHeader().GetCreator(), creator); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &identityImpl{creator}
|
||||
}
|
||||
|
||||
func (t *Transaction) NamespaceReadWriteSets() []NamespaceReadWriteSet {
|
||||
result := []NamespaceReadWriteSet{}
|
||||
for _, readWriteSet := range t.payload.EndorserTransaction().ReadWriteSets() {
|
||||
result = append(result, readWriteSet.NamespaceReadWriteSets()...)
|
||||
func (t *Transaction) NamespaceReadWriteSets() []*NamespaceReadWriteSet {
|
||||
result := []*NamespaceReadWriteSet{}
|
||||
for _, readWriteSet := range t.payload.endorserTransaction().readWriteSets() {
|
||||
result = append(result, readWriteSet.namespaceReadWriteSets()...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO remove unused?
|
||||
func (t *Transaction) ValidationCode() int32 {
|
||||
return t.payload.TransactionValidationCode()
|
||||
}
|
||||
|
||||
// TODO remove unused?
|
||||
func (t *Transaction) IsValid() bool {
|
||||
return t.payload.IsValid()
|
||||
}
|
||||
|
||||
// TODO remove unused?
|
||||
func (t *Transaction) ToProto() *common.Payload {
|
||||
return t.payload.ToProto()
|
||||
}
|
||||
|
||||
// TODO remove interface, use struct; encapsulate; extract into file
|
||||
type EndorserTransaction interface {
|
||||
ReadWriteSets() []ReadWriteSet
|
||||
ToProto() *peer.Transaction
|
||||
}
|
||||
|
||||
type EndorserTransactionImpl struct {
|
||||
transaction *peer.Transaction
|
||||
}
|
||||
|
||||
func ParseEndorserTransaction(transaction *peer.Transaction) *EndorserTransactionImpl {
|
||||
return &EndorserTransactionImpl{transaction}
|
||||
}
|
||||
|
||||
func (p *EndorserTransactionImpl) ReadWriteSets() []ReadWriteSet {
|
||||
return utils.Cache(func() []ReadWriteSet {
|
||||
chaincodeActionPayloads := p.unmarshalChaincodeActionPayloads()
|
||||
|
||||
chaincodeEndorsedActions := p.extractChaincodeEndorsedActionsFrom(chaincodeActionPayloads)
|
||||
|
||||
proposalResponsePayloads := p.unmarshalProposalResponsePayloadsFrom(chaincodeEndorsedActions)
|
||||
|
||||
chaincodeActions := p.unmarshalChaincodeActionsFrom(proposalResponsePayloads)
|
||||
|
||||
txReadWriteSets := p.unmarshalTxReadWriteSetsFrom(chaincodeActions)
|
||||
|
||||
return p.parseReadWriteSets(txReadWriteSets)
|
||||
})()
|
||||
}
|
||||
|
||||
func (p *EndorserTransactionImpl) unmarshalChaincodeActionPayloads() []*peer.ChaincodeActionPayload {
|
||||
result := []*peer.ChaincodeActionPayload{}
|
||||
for _, transactionAction := range p.transaction.GetActions() {
|
||||
chaincodeActionPayload := &peer.ChaincodeActionPayload{}
|
||||
if err := proto.Unmarshal(transactionAction.GetPayload(), chaincodeActionPayload); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result = append(result, chaincodeActionPayload)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*EndorserTransactionImpl) extractChaincodeEndorsedActionsFrom(chaincodeActionPayloads []*peer.ChaincodeActionPayload) []*peer.ChaincodeEndorsedAction {
|
||||
result := []*peer.ChaincodeEndorsedAction{}
|
||||
for _, payload := range chaincodeActionPayloads {
|
||||
result = append(
|
||||
result,
|
||||
utils.AssertDefined(
|
||||
payload.GetAction(),
|
||||
"missing chaincode endorsed action",
|
||||
),
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*EndorserTransactionImpl) unmarshalProposalResponsePayloadsFrom(chaincodeEndorsedActions []*peer.ChaincodeEndorsedAction) []*peer.ProposalResponsePayload {
|
||||
result := []*peer.ProposalResponsePayload{}
|
||||
for _, endorsedAction := range chaincodeEndorsedActions {
|
||||
proposalResponsePayload := &peer.ProposalResponsePayload{}
|
||||
if err := proto.Unmarshal(endorsedAction.GetProposalResponsePayload(), proposalResponsePayload); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result = append(result, proposalResponsePayload)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*EndorserTransactionImpl) unmarshalChaincodeActionsFrom(proposalResponsePayloads []*peer.ProposalResponsePayload) []*peer.ChaincodeAction {
|
||||
result := []*peer.ChaincodeAction{}
|
||||
for _, proposalResponsePayload := range proposalResponsePayloads {
|
||||
chaincodeAction := &peer.ChaincodeAction{}
|
||||
if err := proto.Unmarshal(proposalResponsePayload.GetExtension(), chaincodeAction); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result = append(result, chaincodeAction)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*EndorserTransactionImpl) unmarshalTxReadWriteSetsFrom(chaincodeActions []*peer.ChaincodeAction) []*rwset.TxReadWriteSet {
|
||||
result := []*rwset.TxReadWriteSet{}
|
||||
for _, chaincodeAction := range chaincodeActions {
|
||||
txReadWriteSet := &rwset.TxReadWriteSet{}
|
||||
if err := proto.Unmarshal(chaincodeAction.GetResults(), txReadWriteSet); err != nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, txReadWriteSet)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (*EndorserTransactionImpl) parseReadWriteSets(txReadWriteSets []*rwset.TxReadWriteSet) []ReadWriteSet {
|
||||
result := []ReadWriteSet{}
|
||||
for _, txReadWriteSet := range txReadWriteSets {
|
||||
parsedReadWriteSet := ParseReadWriteSet(txReadWriteSet)
|
||||
result = append(result, parsedReadWriteSet)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO remove unused
|
||||
func (p *EndorserTransactionImpl) ToProto() *peer.Transaction {
|
||||
return p.transaction
|
||||
return t.payload.isValid()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,20 +9,20 @@ import (
|
|||
)
|
||||
|
||||
type block struct {
|
||||
block *parser.Block
|
||||
parsedBlock *parser.Block
|
||||
checkpointer *client.FileCheckpointer
|
||||
writeToStore store.Writer
|
||||
channelName string
|
||||
}
|
||||
|
||||
func NewBlock(
|
||||
_block *parser.Block,
|
||||
parsedBlock *parser.Block,
|
||||
checkpointer *client.FileCheckpointer,
|
||||
writeToStore store.Writer,
|
||||
channelName string,
|
||||
) *block {
|
||||
return &block{
|
||||
_block,
|
||||
parsedBlock,
|
||||
checkpointer,
|
||||
writeToStore,
|
||||
channelName,
|
||||
|
|
@ -30,25 +30,25 @@ func NewBlock(
|
|||
}
|
||||
|
||||
func (b *block) Process() {
|
||||
blockNumber := b.block.Number()
|
||||
blockNumber := b.parsedBlock.Number()
|
||||
|
||||
fmt.Println("\nReceived block", blockNumber)
|
||||
|
||||
for _, transaction := range b.validTransactions() {
|
||||
aTransactionProcessor := transactionProcessor{
|
||||
for _, validTransaction := range b.validTransactions() {
|
||||
aTransaction := transaction{
|
||||
blockNumber,
|
||||
transaction,
|
||||
validTransaction,
|
||||
// TODO use pointer to parent and get blockNumber, store and channelName from parent
|
||||
b.writeToStore,
|
||||
b.channelName,
|
||||
}
|
||||
aTransactionProcessor.process()
|
||||
aTransaction.process()
|
||||
|
||||
transactionId := transaction.ChannelHeader().GetTxId()
|
||||
transactionId := validTransaction.ChannelHeader().GetTxId()
|
||||
b.checkpointer.CheckpointTransaction(blockNumber, transactionId)
|
||||
}
|
||||
|
||||
b.checkpointer.CheckpointBlock(b.block.Number())
|
||||
b.checkpointer.CheckpointBlock(b.parsedBlock.Number())
|
||||
}
|
||||
|
||||
func (b *block) validTransactions() []*parser.Transaction {
|
||||
|
|
@ -62,7 +62,7 @@ func (b *block) validTransactions() []*parser.Transaction {
|
|||
}
|
||||
|
||||
func (b *block) getNewTransactions() []*parser.Transaction {
|
||||
transactions := b.block.Transactions()
|
||||
transactions := b.parsedBlock.Transactions()
|
||||
|
||||
lastTransactionId := b.checkpointer.TransactionID()
|
||||
if lastTransactionId == "" {
|
||||
|
|
@ -77,7 +77,7 @@ func (b *block) getNewTransactions() []*parser.Transaction {
|
|||
|
||||
func (b *block) findLastProcessedIndex() int {
|
||||
blockTransactionIds := []string{}
|
||||
for _, transaction := range b.block.Transactions() {
|
||||
for _, transaction := range b.parsedBlock.Transactions() {
|
||||
blockTransactionIds = append(blockTransactionIds, transaction.ChannelHeader().GetTxId())
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ func (b *block) findLastProcessedIndex() int {
|
|||
fmt.Errorf(
|
||||
"checkpoint transaction ID %s not found in block %d containing transactions: %s",
|
||||
lastTransactionId,
|
||||
b.block.Number(),
|
||||
b.parsedBlock.Number(),
|
||||
b.joinByComma(blockTransactionIds),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import (
|
|||
"slices"
|
||||
)
|
||||
|
||||
type transactionProcessor struct {
|
||||
type transaction struct {
|
||||
blockNumber uint64
|
||||
transaction *parser.Transaction
|
||||
writeToStore store.Writer
|
||||
channelName string
|
||||
}
|
||||
|
||||
func (t *transactionProcessor) process() {
|
||||
func (t *transaction) process() {
|
||||
transactionId := t.transaction.ChannelHeader().GetTxId()
|
||||
|
||||
writes := t.writes()
|
||||
|
|
@ -32,10 +32,12 @@ func (t *transactionProcessor) process() {
|
|||
})
|
||||
}
|
||||
|
||||
func (t *transactionProcessor) writes() []store.Write {
|
||||
func (t *transaction) writes() []store.Write {
|
||||
// TODO this entire code should live in the parser and just return the kvWrite which
|
||||
// we then map to store.Write and return
|
||||
t.channelName = t.transaction.ChannelHeader().GetChannelId()
|
||||
|
||||
nonSystemCCReadWriteSets := []parser.NamespaceReadWriteSet{}
|
||||
nonSystemCCReadWriteSets := []*parser.NamespaceReadWriteSet{}
|
||||
for _, nsReadWriteSet := range t.transaction.NamespaceReadWriteSets() {
|
||||
if !t.isSystemChaincode(nsReadWriteSet.Namespace()) {
|
||||
nonSystemCCReadWriteSets = append(nonSystemCCReadWriteSets, nsReadWriteSet)
|
||||
|
|
@ -60,7 +62,7 @@ func (t *transactionProcessor) writes() []store.Write {
|
|||
return writes
|
||||
}
|
||||
|
||||
func (t *transactionProcessor) isSystemChaincode(chaincodeName string) bool {
|
||||
func (t *transaction) isSystemChaincode(chaincodeName string) bool {
|
||||
systemChaincodeNames := []string{
|
||||
"_lifecycle",
|
||||
"cscc",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func transact(clientConnection *grpc.ClientConn) {
|
|||
|
||||
type transactApp struct {
|
||||
smartContract *atb.AssetTransferBasic
|
||||
batchSize uint
|
||||
batchSize int
|
||||
}
|
||||
|
||||
func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
|
||||
|
|
@ -35,7 +35,7 @@ func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
|
|||
}
|
||||
|
||||
func (t *transactApp) run() {
|
||||
for i := 0; i < int(t.batchSize); i++ {
|
||||
for i := 0; i < t.batchSize; i++ {
|
||||
t.transact()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue