mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-21 17:15: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
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) parse(commonPayloads []*common.Payload) []*PayloadImpl {
|
func (b *Block) parse(commonPayloads []*common.Payload) []*payload {
|
||||||
validationCodes := b.extractTransactionValidationCodes()
|
validationCodes := b.extractTransactionValidationCodes()
|
||||||
result := []*PayloadImpl{}
|
result := []*payload{}
|
||||||
for i, commonPayload := range commonPayloads {
|
for i, commonPayload := range commonPayloads {
|
||||||
payload := ParsePayload(
|
payload := parsePayload(
|
||||||
commonPayload,
|
commonPayload,
|
||||||
int32(utils.AssertDefined(
|
int32(utils.AssertDefined(
|
||||||
validationCodes[i],
|
validationCodes[i],
|
||||||
|
|
@ -70,7 +70,7 @@ func (b *Block) parse(commonPayloads []*common.Payload) []*PayloadImpl {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if payload.IsEndorserTransaction() {
|
if payload.isEndorserTransaction() {
|
||||||
result = append(result, payload)
|
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{}
|
result := []*Transaction{}
|
||||||
for _, payload := range payloads {
|
for _, payload := range payloads {
|
||||||
result = append(result, NewTransaction(payload))
|
result = append(result, newTransaction(payload))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove unused?
|
|
||||||
func (b *Block) ToProto() *common.Block {
|
|
||||||
return b.block
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package parser_test
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
atb "offChainData/contract"
|
atb "offChainData/contract"
|
||||||
"offChainData/parser"
|
|
||||||
|
|
||||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
||||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
||||||
|
|
@ -35,13 +34,13 @@ func Test_GetReadWriteSetsFromEndorserTransaction(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedEndorserTransaction := parser.ParseEndorserTransaction(transaction)
|
parsedEndorserTransaction := parseEndorserTransaction(transaction)
|
||||||
if len(parsedEndorserTransaction.ReadWriteSets()) != 1 {
|
if len(parsedEndorserTransaction.readWriteSets()) != 1 {
|
||||||
t.Fatal("expected 1 ReadWriteSet, got", len(parsedEndorserTransaction.ReadWriteSets()))
|
t.Fatal("expected 1 ReadWriteSet, got", len(parsedEndorserTransaction.readWriteSets()))
|
||||||
}
|
}
|
||||||
|
|
||||||
assertReadWriteSet(
|
assertReadWriteSet(
|
||||||
parsedEndorserTransaction.ReadWriteSets()[0].NamespaceReadWriteSets()[0],
|
parsedEndorserTransaction.readWriteSets()[0].namespaceReadWriteSets()[0],
|
||||||
expectedNamespace,
|
expectedNamespace,
|
||||||
expectedAsset,
|
expectedAsset,
|
||||||
t,
|
t,
|
||||||
|
|
@ -49,7 +48,7 @@ func Test_GetReadWriteSetsFromEndorserTransaction(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertReadWriteSet(
|
func assertReadWriteSet(
|
||||||
parsedNsRwSet parser.NamespaceReadWriteSet,
|
parsedNsRwSet *NamespaceReadWriteSet,
|
||||||
expectedNamespace string,
|
expectedNamespace string,
|
||||||
expectedAsset atb.Asset,
|
expectedAsset atb.Asset,
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
|
|
@ -80,16 +79,16 @@ func Test_ReadWriteSetWrapping(t *testing.T) {
|
||||||
NsRwset: []*rwset.NsReadWriteSet{nsReadWriteSetFake},
|
NsRwset: []*rwset.NsReadWriteSet{nsReadWriteSetFake},
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedRwSet := parser.ParseReadWriteSet(txReadWriteSetFake)
|
parsedRwSet := parseReadWriteSet(txReadWriteSetFake)
|
||||||
if len(parsedRwSet.NamespaceReadWriteSets()) != 1 {
|
if len(parsedRwSet.namespaceReadWriteSets()) != 1 {
|
||||||
t.Fatalf("Expected 1 NamespaceReadWriteSet, got %d", len(parsedRwSet.NamespaceReadWriteSets()))
|
t.Fatalf("Expected 1 NamespaceReadWriteSet, got %d", len(parsedRwSet.namespaceReadWriteSets()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_NamespaceReadWriteSetParsing(t *testing.T) {
|
func Test_NamespaceReadWriteSetParsing(t *testing.T) {
|
||||||
nsReadWriteSetFake, expectedNamespace, expectedAsset := nsReadWriteSetFake()
|
nsReadWriteSetFake, expectedNamespace, expectedAsset := nsReadWriteSetFake()
|
||||||
|
|
||||||
parsedNsRwSet := parser.ParseNamespaceReadWriteSet(nsReadWriteSetFake)
|
parsedNsRwSet := parseNamespaceReadWriteSet(nsReadWriteSetFake)
|
||||||
assertReadWriteSet(
|
assertReadWriteSet(
|
||||||
parsedNsRwSet,
|
parsedNsRwSet,
|
||||||
expectedNamespace,
|
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"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO remove interface, use struct; encapsulate
|
type payload struct {
|
||||||
type Payload interface {
|
commonPayload *common.Payload
|
||||||
ChannelHeader() *common.ChannelHeader
|
statusCode int32
|
||||||
EndorserTransaction() EndorserTransaction
|
|
||||||
SignatureHeader() *common.SignatureHeader
|
|
||||||
TransactionValidationCode() int32
|
|
||||||
IsEndorserTransaction() bool
|
|
||||||
IsValid() bool
|
|
||||||
ToProto() *common.Payload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PayloadImpl struct {
|
func parsePayload(commonPayload *common.Payload, statusCode int32) *payload {
|
||||||
payload *common.Payload
|
return &payload{commonPayload, statusCode}
|
||||||
statusCode int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParsePayload(payload *common.Payload, statusCode int32) *PayloadImpl {
|
func (p *payload) channelHeader() *common.ChannelHeader {
|
||||||
return &PayloadImpl{payload, statusCode}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PayloadImpl) ChannelHeader() *common.ChannelHeader {
|
|
||||||
return utils.Cache(func() *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{}
|
result := &common.ChannelHeader{}
|
||||||
if err := proto.Unmarshal(header.GetChannelHeader(), result); err != nil {
|
if err := proto.Unmarshal(header.GetChannelHeader(), result); err != nil {
|
||||||
|
|
@ -42,45 +31,23 @@ func (p *PayloadImpl) ChannelHeader() *common.ChannelHeader {
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PayloadImpl) EndorserTransaction() EndorserTransaction {
|
func (p *payload) endorserTransaction() *endorserTransaction {
|
||||||
if !p.IsEndorserTransaction() {
|
if !p.isEndorserTransaction() {
|
||||||
panic(fmt.Errorf("unexpected payload type: %d", p.ChannelHeader().GetType()))
|
panic(fmt.Errorf("unexpected payload type: %d", p.channelHeader().GetType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
result := &peer.Transaction{}
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseEndorserTransaction(result)
|
return parseEndorserTransaction(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PayloadImpl) SignatureHeader() *common.SignatureHeader {
|
func (p *payload) isEndorserTransaction() bool {
|
||||||
return utils.Cache(func() *common.SignatureHeader {
|
return p.channelHeader().GetType() == int32(common.HeaderType_ENDORSER_TRANSACTION)
|
||||||
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 *PayloadImpl) TransactionValidationCode() int32 {
|
func (p *payload) isValid() bool {
|
||||||
return p.statusCode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PayloadImpl) IsEndorserTransaction() bool {
|
|
||||||
return p.ChannelHeader().GetType() == int32(common.HeaderType_ENDORSER_TRANSACTION)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PayloadImpl) IsValid() bool {
|
|
||||||
return p.statusCode == int32(peer.TxValidationCode_VALID)
|
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
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"offChainData/utils"
|
|
||||||
|
|
||||||
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
"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 struct {
|
||||||
type ReadWriteSet interface {
|
|
||||||
NamespaceReadWriteSets() []NamespaceReadWriteSet
|
|
||||||
ToProto() *rwset.TxReadWriteSet
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReadWriteSetImpl struct {
|
|
||||||
readWriteSet *rwset.TxReadWriteSet
|
readWriteSet *rwset.TxReadWriteSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseReadWriteSet(rwSet *rwset.TxReadWriteSet) *ReadWriteSetImpl {
|
func parseReadWriteSet(rwSet *rwset.TxReadWriteSet) *readWriteSet {
|
||||||
return &ReadWriteSetImpl{rwSet}
|
return &readWriteSet{rwSet}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReadWriteSetImpl) NamespaceReadWriteSets() []NamespaceReadWriteSet {
|
func (p *readWriteSet) namespaceReadWriteSets() []*NamespaceReadWriteSet {
|
||||||
result := []NamespaceReadWriteSet{}
|
result := []*NamespaceReadWriteSet{}
|
||||||
for _, nsReadWriteSet := range p.readWriteSet.GetNsRwset() {
|
for _, nsReadWriteSet := range p.readWriteSet.GetNsRwset() {
|
||||||
parsedNamespaceReadWriteSet := ParseNamespaceReadWriteSet(nsReadWriteSet)
|
parsedNamespaceReadWriteSet := parseNamespaceReadWriteSet(nsReadWriteSet)
|
||||||
result = append(result, parsedNamespaceReadWriteSet)
|
result = append(result, parsedNamespaceReadWriteSet)
|
||||||
}
|
}
|
||||||
return result
|
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
|
package parser
|
||||||
|
|
||||||
import (
|
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/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 {
|
type Transaction struct {
|
||||||
payload Payload
|
payload *payload
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransaction(payload Payload) *Transaction {
|
func newTransaction(payload *payload) *Transaction {
|
||||||
return &Transaction{payload}
|
return &Transaction{payload}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transaction) ChannelHeader() *common.ChannelHeader {
|
func (t *Transaction) ChannelHeader() *common.ChannelHeader {
|
||||||
return t.payload.ChannelHeader()
|
return t.payload.channelHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove unused?
|
func (t *Transaction) NamespaceReadWriteSets() []*NamespaceReadWriteSet {
|
||||||
func (t *Transaction) Creator() identity.Identity {
|
result := []*NamespaceReadWriteSet{}
|
||||||
creator := &msp.SerializedIdentity{}
|
for _, readWriteSet := range t.payload.endorserTransaction().readWriteSets() {
|
||||||
if err := proto.Unmarshal(t.payload.SignatureHeader().GetCreator(), creator); err != nil {
|
result = append(result, readWriteSet.namespaceReadWriteSets()...)
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &identityImpl{creator}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transaction) NamespaceReadWriteSets() []NamespaceReadWriteSet {
|
|
||||||
result := []NamespaceReadWriteSet{}
|
|
||||||
for _, readWriteSet := range t.payload.EndorserTransaction().ReadWriteSets() {
|
|
||||||
result = append(result, readWriteSet.NamespaceReadWriteSets()...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove unused?
|
|
||||||
func (t *Transaction) ValidationCode() int32 {
|
|
||||||
return t.payload.TransactionValidationCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO remove unused?
|
|
||||||
func (t *Transaction) IsValid() bool {
|
func (t *Transaction) IsValid() bool {
|
||||||
return t.payload.IsValid()
|
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
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type block struct {
|
type block struct {
|
||||||
block *parser.Block
|
parsedBlock *parser.Block
|
||||||
checkpointer *client.FileCheckpointer
|
checkpointer *client.FileCheckpointer
|
||||||
writeToStore store.Writer
|
writeToStore store.Writer
|
||||||
channelName string
|
channelName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlock(
|
func NewBlock(
|
||||||
_block *parser.Block,
|
parsedBlock *parser.Block,
|
||||||
checkpointer *client.FileCheckpointer,
|
checkpointer *client.FileCheckpointer,
|
||||||
writeToStore store.Writer,
|
writeToStore store.Writer,
|
||||||
channelName string,
|
channelName string,
|
||||||
) *block {
|
) *block {
|
||||||
return &block{
|
return &block{
|
||||||
_block,
|
parsedBlock,
|
||||||
checkpointer,
|
checkpointer,
|
||||||
writeToStore,
|
writeToStore,
|
||||||
channelName,
|
channelName,
|
||||||
|
|
@ -30,25 +30,25 @@ func NewBlock(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *block) Process() {
|
func (b *block) Process() {
|
||||||
blockNumber := b.block.Number()
|
blockNumber := b.parsedBlock.Number()
|
||||||
|
|
||||||
fmt.Println("\nReceived block", blockNumber)
|
fmt.Println("\nReceived block", blockNumber)
|
||||||
|
|
||||||
for _, transaction := range b.validTransactions() {
|
for _, validTransaction := range b.validTransactions() {
|
||||||
aTransactionProcessor := transactionProcessor{
|
aTransaction := transaction{
|
||||||
blockNumber,
|
blockNumber,
|
||||||
transaction,
|
validTransaction,
|
||||||
// TODO use pointer to parent and get blockNumber, store and channelName from parent
|
// TODO use pointer to parent and get blockNumber, store and channelName from parent
|
||||||
b.writeToStore,
|
b.writeToStore,
|
||||||
b.channelName,
|
b.channelName,
|
||||||
}
|
}
|
||||||
aTransactionProcessor.process()
|
aTransaction.process()
|
||||||
|
|
||||||
transactionId := transaction.ChannelHeader().GetTxId()
|
transactionId := validTransaction.ChannelHeader().GetTxId()
|
||||||
b.checkpointer.CheckpointTransaction(blockNumber, transactionId)
|
b.checkpointer.CheckpointTransaction(blockNumber, transactionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.checkpointer.CheckpointBlock(b.block.Number())
|
b.checkpointer.CheckpointBlock(b.parsedBlock.Number())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *block) validTransactions() []*parser.Transaction {
|
func (b *block) validTransactions() []*parser.Transaction {
|
||||||
|
|
@ -62,7 +62,7 @@ func (b *block) validTransactions() []*parser.Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *block) getNewTransactions() []*parser.Transaction {
|
func (b *block) getNewTransactions() []*parser.Transaction {
|
||||||
transactions := b.block.Transactions()
|
transactions := b.parsedBlock.Transactions()
|
||||||
|
|
||||||
lastTransactionId := b.checkpointer.TransactionID()
|
lastTransactionId := b.checkpointer.TransactionID()
|
||||||
if lastTransactionId == "" {
|
if lastTransactionId == "" {
|
||||||
|
|
@ -77,7 +77,7 @@ func (b *block) getNewTransactions() []*parser.Transaction {
|
||||||
|
|
||||||
func (b *block) findLastProcessedIndex() int {
|
func (b *block) findLastProcessedIndex() int {
|
||||||
blockTransactionIds := []string{}
|
blockTransactionIds := []string{}
|
||||||
for _, transaction := range b.block.Transactions() {
|
for _, transaction := range b.parsedBlock.Transactions() {
|
||||||
blockTransactionIds = append(blockTransactionIds, transaction.ChannelHeader().GetTxId())
|
blockTransactionIds = append(blockTransactionIds, transaction.ChannelHeader().GetTxId())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ func (b *block) findLastProcessedIndex() int {
|
||||||
fmt.Errorf(
|
fmt.Errorf(
|
||||||
"checkpoint transaction ID %s not found in block %d containing transactions: %s",
|
"checkpoint transaction ID %s not found in block %d containing transactions: %s",
|
||||||
lastTransactionId,
|
lastTransactionId,
|
||||||
b.block.Number(),
|
b.parsedBlock.Number(),
|
||||||
b.joinByComma(blockTransactionIds),
|
b.joinByComma(blockTransactionIds),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type transactionProcessor struct {
|
type transaction struct {
|
||||||
blockNumber uint64
|
blockNumber uint64
|
||||||
transaction *parser.Transaction
|
transaction *parser.Transaction
|
||||||
writeToStore store.Writer
|
writeToStore store.Writer
|
||||||
channelName string
|
channelName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *transactionProcessor) process() {
|
func (t *transaction) process() {
|
||||||
transactionId := t.transaction.ChannelHeader().GetTxId()
|
transactionId := t.transaction.ChannelHeader().GetTxId()
|
||||||
|
|
||||||
writes := t.writes()
|
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()
|
t.channelName = t.transaction.ChannelHeader().GetChannelId()
|
||||||
|
|
||||||
nonSystemCCReadWriteSets := []parser.NamespaceReadWriteSet{}
|
nonSystemCCReadWriteSets := []*parser.NamespaceReadWriteSet{}
|
||||||
for _, nsReadWriteSet := range t.transaction.NamespaceReadWriteSets() {
|
for _, nsReadWriteSet := range t.transaction.NamespaceReadWriteSets() {
|
||||||
if !t.isSystemChaincode(nsReadWriteSet.Namespace()) {
|
if !t.isSystemChaincode(nsReadWriteSet.Namespace()) {
|
||||||
nonSystemCCReadWriteSets = append(nonSystemCCReadWriteSets, nsReadWriteSet)
|
nonSystemCCReadWriteSets = append(nonSystemCCReadWriteSets, nsReadWriteSet)
|
||||||
|
|
@ -60,7 +62,7 @@ func (t *transactionProcessor) writes() []store.Write {
|
||||||
return writes
|
return writes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *transactionProcessor) isSystemChaincode(chaincodeName string) bool {
|
func (t *transaction) isSystemChaincode(chaincodeName string) bool {
|
||||||
systemChaincodeNames := []string{
|
systemChaincodeNames := []string{
|
||||||
"_lifecycle",
|
"_lifecycle",
|
||||||
"cscc",
|
"cscc",
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func transact(clientConnection *grpc.ClientConn) {
|
||||||
|
|
||||||
type transactApp struct {
|
type transactApp struct {
|
||||||
smartContract *atb.AssetTransferBasic
|
smartContract *atb.AssetTransferBasic
|
||||||
batchSize uint
|
batchSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
|
func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
|
||||||
|
|
@ -35,7 +35,7 @@ func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *transactApp) run() {
|
func (t *transactApp) run() {
|
||||||
for i := 0; i < int(t.batchSize); i++ {
|
for i := 0; i < t.batchSize; i++ {
|
||||||
t.transact()
|
t.transact()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue