Skip to content

Commit

Permalink
Merge pull request #99 from kaleido-io/pdc
Browse files Browse the repository at this point in the history
Add transient map support in transaction submission
  • Loading branch information
jimthematrix authored Nov 4, 2022
2 parents 1df7cbb + 3bf447f commit 62dd202
Show file tree
Hide file tree
Showing 15 changed files with 314 additions and 280 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ firefly-fabconnect
fabconnect
fabconnect-nocgo
coverage.txt
__debug_bin

# Others
/.vscode/
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ require (
)

replace google.golang.org/grpc => google.golang.org/grpc v1.29.0

replace github.com/hyperledger/fabric-sdk-go => github.com/kaleido-io/fabric-sdk-go v1.0.1-0.20221104172459-a5cbbfd0c1d6
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,6 @@ github.com/hyperledger/fabric-lib-go v1.0.0/go.mod h1:H362nMlunurmHwkYqR5uHL2UDW
github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-protos-go v0.0.0-20211118165945-23d738fc3553 h1:E9f0v1q4EDfrE+0LdkxVtdYKAZ7PGCaj1bBx45R9yEQ=
github.com/hyperledger/fabric-protos-go v0.0.0-20211118165945-23d738fc3553/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-sdk-go v1.0.1-0.20220617091732-e170b98fa821 h1:0VfkWCv8MPDjm+6xoD6t3yN075AQ2x2KTcLY1m5BJno=
github.com/hyperledger/fabric-sdk-go v1.0.1-0.20220617091732-e170b98fa821/go.mod h1:JRplpKBeAvXjsBhOCCM/KvMRUbdDyhsAh80qbXzKc10=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
Expand Down Expand Up @@ -431,6 +429,8 @@ github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSg
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kaleido-io/fabric-sdk-go v1.0.1-0.20221104172459-a5cbbfd0c1d6 h1:pNshpmQHZ48yUgUyYRD8xXo7b0z47Sqoyl6aHUMVYkg=
github.com/kaleido-io/fabric-sdk-go v1.0.1-0.20221104172459-a5cbbfd0c1d6/go.mod h1:JRplpKBeAvXjsBhOCCM/KvMRUbdDyhsAh80qbXzKc10=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
Expand Down
2 changes: 1 addition & 1 deletion internal/fabric/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type RegistrationWrapper struct {
}

type RPCClient interface {
Invoke(channelId, signer, chaincodeName, method string, args []string, isInit bool) (*TxReceipt, error)
Invoke(channelId, signer, chaincodeName, method string, args []string, transientMap map[string]string, isInit bool) (*TxReceipt, error)
Query(channelId, signer, chaincodeName, method string, args []string, strongread bool) ([]byte, error)
QueryChainInfo(channelId, signer string) (*fab.BlockchainInfoResponse, error)
QueryBlock(channelId string, signer string, blocknumber uint64, blockhash []byte) (*utils.RawBlock, *utils.Block, error)
Expand Down
17 changes: 9 additions & 8 deletions internal/fabric/client/client_ccp.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ func newRPCClientFromCCP(configProvider core.ConfigProvider, txTimeout int, user
return w, nil
}

func (w *ccpRPCWrapper) Invoke(channelId, signer, chaincodeName, method string, args []string, isInit bool) (*TxReceipt, error) {
func (w *ccpRPCWrapper) Invoke(channelId, signer, chaincodeName, method string, args []string, transientMap map[string]string, isInit bool) (*TxReceipt, error) {
log.Tracef("RPC [%s:%s:%s:isInit=%t] --> %+v", channelId, chaincodeName, method, isInit, args)

signerID, result, txStatus, err := w.sendTransaction(channelId, signer, chaincodeName, method, args, isInit)
signerID, result, txStatus, err := w.sendTransaction(channelId, signer, chaincodeName, method, args, transientMap, isInit)
if err != nil {
log.Errorf("Failed to send transaction [%s:%s:%s:isInit=%t]. %s", channelId, chaincodeName, method, isInit, err)
return nil, err
Expand All @@ -107,7 +107,7 @@ func (w *ccpRPCWrapper) Query(channelId, signer, chaincodeName, method string, a
req := channel.Request{
ChaincodeID: chaincodeName,
Fcn: method,
Args: convert(args),
Args: convertStringArray(args),
}

var result channel.Response
Expand Down Expand Up @@ -178,7 +178,7 @@ func (w *ccpRPCWrapper) Close() error {
return nil
}

func (w *ccpRPCWrapper) sendTransaction(channelId, signer, chaincodeName, method string, args []string, isInit bool) (*msp.IdentityIdentifier, []byte, *fab.TxStatusEvent, error) {
func (w *ccpRPCWrapper) sendTransaction(channelId, signer, chaincodeName, method string, args []string, transientMap map[string]string, isInit bool) (*msp.IdentityIdentifier, []byte, *fab.TxStatusEvent, error) {
client, err := w.getChannelClient(channelId, signer)
if err != nil {
return nil, nil, nil, errors.Errorf("Failed to get channel client. %s", err)
Expand All @@ -197,10 +197,11 @@ func (w *ccpRPCWrapper) sendTransaction(channelId, signer, chaincodeName, method
result, err := client.channelClient.InvokeHandler(
handlerChain,
channel.Request{
ChaincodeID: chaincodeName,
Fcn: method,
Args: convert(args),
IsInit: isInit,
ChaincodeID: chaincodeName,
Fcn: method,
Args: convertStringArray(args),
TransientMap: convertStringMap(transientMap),
IsInit: isInit,
},
channel.WithRetry(retry.DefaultChannelOpts),
)
Expand Down
10 changes: 9 additions & 1 deletion internal/fabric/client/client_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,22 @@ func newReceipt(responsePayload []byte, status *fab.TxStatusEvent, signerID *msp
}
}

func convert(args []string) [][]byte {
func convertStringArray(args []string) [][]byte {
result := [][]byte{}
for _, v := range args {
result = append(result, []byte(v))
}
return result
}

func convertStringMap(_map map[string]string) map[string][]byte {
result := make(map[string][]byte, len(_map))
for k, v := range _map {
result[k] = []byte(v)
}
return result
}

func (w *commonRPCWrapper) QueryChainInfo(channelId, signer string) (*fab.BlockchainInfoResponse, error) {
log.Tracef("RPC [%s] --> QueryChainInfo", channelId)

Expand Down
18 changes: 10 additions & 8 deletions internal/fabric/client/client_gateway_clientside.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
type gatewayCreator func(core.ConfigProvider, string, int) (*gateway.Gateway, error)
type networkCreator func(*gateway.Gateway, string) (*gateway.Network, error)
type txPreparer func(*gwRPCWrapper, string, string, string, string, bool) (*gateway.Transaction, <-chan *fab.TxStatusEvent, error)
type txSubmitter func(*gateway.Transaction, ...string) ([]byte, error)
type txSubmitter func(*gateway.Transaction, map[string][]byte, ...string) ([]byte, error)

type gwRPCWrapper struct {
*commonRPCWrapper
Expand Down Expand Up @@ -76,10 +76,10 @@ func newRPCClientWithClientSideGateway(configProvider core.ConfigProvider, txTim
return w, nil
}

func (w *gwRPCWrapper) Invoke(channelId, signer, chaincodeName, method string, args []string, isInit bool) (*TxReceipt, error) {
func (w *gwRPCWrapper) Invoke(channelId, signer, chaincodeName, method string, args []string, transientMap map[string]string, isInit bool) (*TxReceipt, error) {
log.Tracef("RPC [%s:%s:%s:isInit=%t] --> %+v", channelId, chaincodeName, method, isInit, args)

result, txStatus, err := w.sendTransaction(channelId, signer, chaincodeName, method, args, isInit)
result, txStatus, err := w.sendTransaction(channelId, signer, chaincodeName, method, args, transientMap, isInit)
if err != nil {
log.Errorf("Failed to send transaction [%s:%s:%s:isInit=%t]. %s", channelId, chaincodeName, method, isInit, err)
return nil, err
Expand Down Expand Up @@ -121,7 +121,7 @@ func (w *gwRPCWrapper) Query(channelId, signer, chaincodeName, method string, ar
return nil, err
}

bytes := convert(args)
bytes := convertStringArray(args)
req := channel.Request{
ChaincodeID: chaincodeName,
Fcn: method,
Expand Down Expand Up @@ -153,12 +153,14 @@ func (w *gwRPCWrapper) Close() error {
return nil
}

func (w *gwRPCWrapper) sendTransaction(signer, channelId, chaincodeName, method string, args []string, isInit bool) ([]byte, *fab.TxStatusEvent, error) {
func (w *gwRPCWrapper) sendTransaction(signer, channelId, chaincodeName, method string, args []string, transientMap map[string]string, isInit bool) ([]byte, *fab.TxStatusEvent, error) {
tx, notifier, err := w.txPreparer(w, signer, channelId, chaincodeName, method, isInit)
if err != nil {
return nil, nil, err
}
result, err := w.txSubmitter(tx, args...)
var result []byte
convertedMap := convertStringMap(transientMap)
result, err = w.txSubmitter(tx, convertedMap, args...)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -261,6 +263,6 @@ func prepareTx(w *gwRPCWrapper, signer, channelId, chaincodeName, method string,
return tx, notifier, nil
}

func submitTx(tx *gateway.Transaction, args ...string) ([]byte, error) {
return tx.Submit(args...)
func submitTx(tx *gateway.Transaction, transientMap map[string][]byte, args ...string) ([]byte, error) {
return tx.SubmitWithTransientMap(transientMap, args...)
}
12 changes: 8 additions & 4 deletions internal/fabric/client/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,15 @@ func TestGatewayClientSendTx(t *testing.T) {
}()
return nil, notifier, nil
}
mockSubmitTx := func(tx *gateway.Transaction, args ...string) ([]byte, error) {
mockSubmitTx := func(tx *gateway.Transaction, transientMap map[string][]byte, args ...string) ([]byte, error) {
return []byte(""), nil
}
wrapper.txPreparer = mockPrepareTx
wrapper.txSubmitter = mockSubmitTx

_, _, err = wrapper.sendTransaction("signer1", "channel-1", "chaincode-1", "method-1", []string{"args-1"}, false)
testmap := make(map[string]string)
testmap["entry-1"] = "value-1"
_, _, err = wrapper.sendTransaction("signer1", "channel-1", "chaincode-1", "method-1", []string{"args-1"}, testmap, false)
assert.NoError(err)
}

Expand Down Expand Up @@ -275,13 +277,15 @@ func TestGatewayClientSendInitTx(t *testing.T) {
}()
return nil, notifier, nil
}
mockSubmitTx := func(tx *gateway.Transaction, args ...string) ([]byte, error) {
mockSubmitTx := func(tx *gateway.Transaction, transientMap map[string][]byte, args ...string) ([]byte, error) {
return []byte(""), nil
}
wrapper.txPreparer = mockPrepareTx
wrapper.txSubmitter = mockSubmitTx

_, _, err = wrapper.sendTransaction("signer1", "channel-1", "chaincode-1", "method-1", []string{"args-1"}, true)
testmap := make(map[string]string)
testmap["entry-1"] = "value-1"
_, _, err = wrapper.sendTransaction("signer1", "channel-1", "chaincode-1", "method-1", []string{"args-1"}, testmap, true)
assert.NoError(err)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/fabric/test/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func MockRPCClient(fromBlock string, withReset ...bool) *mockfabric.RPCClient {
},
}
tx1 := &utils.Transaction{
Timestamp: int64(1000000),
Timestamp: 1000000,
TxId: "3144a3ad43dcc11374832bbb71561320de81fd80d69cc8e26a9ea7d3240a5e84",
}
block := &utils.Block{
Expand Down
4 changes: 3 additions & 1 deletion internal/fabric/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Tx struct {
IsInit bool
Function string
Args []string
TransientMap map[string]string
Hash string
Receipt *client.TxReceipt
Signer string
Expand All @@ -48,6 +49,7 @@ func NewSendTx(msg *messages.SendTransaction, signer string) *Tx {
IsInit: msg.IsInit,
Function: msg.Function,
Args: msg.Args,
TransientMap: msg.TransientMap,
Signer: msg.Headers.Signer,
}
}
Expand All @@ -66,7 +68,7 @@ func (tx *Tx) Send(ctx context.Context, rpc client.RPCClient) error {

var receipt *client.TxReceipt
var err error
receipt, err = rpc.Invoke(tx.ChannelID, tx.Signer, tx.ChaincodeName, tx.Function, tx.Args, tx.IsInit)
receipt, err = rpc.Invoke(tx.ChannelID, tx.Signer, tx.ChaincodeName, tx.Function, tx.Args, tx.TransientMap, tx.IsInit)
tx.lock.Lock()
tx.Receipt = receipt
tx.lock.Unlock()
Expand Down
3 changes: 2 additions & 1 deletion internal/fabric/utils/blockdecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/base64"
"encoding/hex"
"strconv"
"time"

"github.com/golang/protobuf/proto" //nolint
"github.com/hyperledger/fabric-protos-go/common"
Expand Down Expand Up @@ -204,7 +205,7 @@ func (block *RawBlock) decodePayloadHeader(header *common.Header, _header *Paylo
}
_channelHeader.ChannelId = channelHeader.ChannelId
_channelHeader.Epoch = strconv.FormatUint(channelHeader.Epoch, 10)
_channelHeader.Timestamp = channelHeader.Timestamp.AsTime().UnixNano()
_channelHeader.Timestamp = time.Unix(channelHeader.Timestamp.GetSeconds(), int64(channelHeader.Timestamp.GetNanos())).UnixNano()
_channelHeader.TxId = channelHeader.TxId
_channelHeader.Type = common.HeaderType_name[channelHeader.Type]
_channelHeader.Version = int(channelHeader.Version)
Expand Down
7 changes: 4 additions & 3 deletions internal/messages/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,10 @@ type GetBlockByTxId struct {
// SendTransaction message instructs the bridge to install a contract
type SendTransaction struct {
RequestCommon
IsInit bool `json:"init"`
Function string `json:"func"`
Args []string `json:"args,omitempty"`
IsInit bool `json:"init"`
Function string `json:"func"`
Args []string `json:"args,omitempty"`
TransientMap map[string]string `json:"transientMap,omitempty"`
}

// DeployChaincode message instructs the bridge to install a contract
Expand Down
8 changes: 8 additions & 0 deletions internal/rest/utils/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ func BuildTxMessage(res http.ResponseWriter, req *http.Request, params httproute
return nil, nil, NewRestError(err.Error(), 400)
}
msg.Args = argsVal
transientMap := body["transientMap"]
if transientMap != nil {
tmpMap := transientMap.(map[string]interface{})
msg.TransientMap = make(map[string]string, len(tmpMap))
for k, v := range tmpMap {
msg.TransientMap[k] = v.(string)
}
}

opts := TxOpts{}
opts.Sync = true
Expand Down
14 changes: 7 additions & 7 deletions mocks/fabric/client/rpc_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 62dd202

Please sign in to comment.