diff --git a/pkg/gateway/contract_test.go b/pkg/gateway/contract_test.go index 4561b73d11..aa5ed2d494 100644 --- a/pkg/gateway/contract_test.go +++ b/pkg/gateway/contract_test.go @@ -38,7 +38,13 @@ func TestCreateTransaction(t *testing.T) { func TestSubmitTransaction(t *testing.T) { c := mockChannelProvider("mychannel") - gw := &Gateway{} + gw := &Gateway{ + options: &gatewayOptions{ + CommitHandler: DefaultCommitHandlers.OrgAll, + Discovery: defaultDiscovery, + Timeout: defaultTimeout, + }, + } nw, err := newNetwork(gw, c) @@ -62,7 +68,13 @@ func TestSubmitTransaction(t *testing.T) { func TestEvaluateTransaction(t *testing.T) { c := mockChannelProvider("mychannel") - gw := &Gateway{} + gw := &Gateway{ + options: &gatewayOptions{ + CommitHandler: DefaultCommitHandlers.OrgAll, + Discovery: defaultDiscovery, + Timeout: defaultTimeout, + }, + } nw, err := newNetwork(gw, c) diff --git a/pkg/gateway/gateway.go b/pkg/gateway/gateway.go index e93d31c868..990e03535f 100644 --- a/pkg/gateway/gateway.go +++ b/pkg/gateway/gateway.go @@ -8,6 +8,7 @@ package gateway import ( "fmt" + "time" "github.com/hyperledger/fabric-sdk-go/pkg/client/msp" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context" @@ -17,6 +18,11 @@ import ( "github.com/pkg/errors" ) +const ( + defaultTimeout = 5 * time.Minute + defaultDiscovery = true +) + // Gateway is the entry point to a Fabric network type Gateway struct { sdk *fabsdk.FabricSDK @@ -30,6 +36,7 @@ type gatewayOptions struct { User string CommitHandler CommitHandlerFactory Discovery bool + Timeout time.Duration } // Option functional arguments can be supplied when connecting to the gateway. @@ -48,7 +55,8 @@ func Connect(config ConfigOption, identity IdentityOption, options ...Option) (* g := &Gateway{ options: &gatewayOptions{ CommitHandler: DefaultCommitHandlers.OrgAll, - Discovery: true, + Discovery: defaultDiscovery, + Timeout: defaultTimeout, }, } @@ -185,6 +193,15 @@ func WithDiscovery(discovery bool) Option { } } +// WithTimeout is an optional argument to the Connect method which +// defines the commit timeout for all transaction submissions for this gateway. +func WithTimeout(timeout time.Duration) Option { + return func(gw *Gateway) error { + gw.options.Timeout = timeout + return nil + } +} + func (gw *Gateway) getSDK() *fabsdk.FabricSDK { return gw.sdk } diff --git a/pkg/gateway/gateway_test.go b/pkg/gateway/gateway_test.go index 56c72691e2..47159315b5 100644 --- a/pkg/gateway/gateway_test.go +++ b/pkg/gateway/gateway_test.go @@ -9,6 +9,7 @@ package gateway import ( "reflect" "testing" + "time" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" @@ -71,6 +72,10 @@ func TestConnectNoOptions(t *testing.T) { if options.Discovery != true { t.Fatal("Discovery not correctly initialized") } + + if options.Timeout != defaultTimeout { + t.Fatal("Timeout not correctly initialized") + } } func TestConnectWithSDK(t *testing.T) { @@ -98,6 +103,10 @@ func TestConnectWithSDK(t *testing.T) { if options.Discovery != true { t.Fatal("Discovery not correctly initialized") } + + if options.Timeout != defaultTimeout { + t.Fatal("Timeout not correctly initialized") + } } func TestConnectWithIdentity(t *testing.T) { @@ -158,6 +167,23 @@ func TestConnectWithDiscovery(t *testing.T) { } } +func TestConnectWithTimout(t *testing.T) { + gw, err := Connect( + WithConfig(config.FromFile("testdata/connection-tls.json")), + WithUser("user1"), + WithTimeout(20*time.Second), + ) + if err != nil { + t.Fatalf("Failed to create gateway: %s", err) + } + + options := gw.options + + if options.Timeout != 20*time.Second { + t.Fatal("Timeout not set correctly") + } +} + func TestConnectWithMultipleOptions(t *testing.T) { gw, err := Connect( WithConfig(config.FromFile("testdata/connection-tls.json")), diff --git a/pkg/gateway/transaction.go b/pkg/gateway/transaction.go index e2c71723be..cb3ce25d87 100644 --- a/pkg/gateway/transaction.go +++ b/pkg/gateway/transaction.go @@ -8,6 +8,7 @@ package gateway import ( "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" + "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" "github.com/pkg/errors" ) @@ -76,7 +77,13 @@ func (txn *Transaction) Evaluate(args ...string) ([]byte, error) { } txn.request.Args = bytes - response, err := txn.contract.client.Query(*txn.request, channel.WithTargets(txn.contract.network.peers[0])) + var options []channel.RequestOption + options = append(options, channel.WithTimeout(fab.Query, txn.contract.network.gateway.options.Timeout)) + + response, err := txn.contract.client.Query( + *txn.request, + options..., + ) if err != nil { return nil, errors.Wrap(err, "Failed to evaluate") } @@ -94,7 +101,16 @@ func (txn *Transaction) Submit(args ...string) ([]byte, error) { } txn.request.Args = bytes - response, err := txn.contract.client.Execute(*txn.request) + var options []channel.RequestOption + if txn.endorsingPeers != nil { + options = append(options, channel.WithTargetEndpoints(txn.endorsingPeers...)) + } + options = append(options, channel.WithTimeout(fab.Execute, txn.contract.network.gateway.options.Timeout)) + + response, err := txn.contract.client.Execute( + *txn.request, + options..., + ) if err != nil { return nil, errors.Wrap(err, "Failed to submit") } diff --git a/test/integration/pkg/gateway/gateway.go b/test/integration/pkg/gateway/gateway.go index 1516c4b3e5..8976eaedd6 100644 --- a/test/integration/pkg/gateway/gateway.go +++ b/test/integration/pkg/gateway/gateway.go @@ -98,6 +98,28 @@ func RunWithWallet(t *testing.T) { testGateway(gw, t) } +// RunWithTransient tests sending transient data +func RunWithTransient(t *testing.T) { + configPath := integration.GetConfigPath("config_e2e.yaml") + + gw, err := gateway.Connect( + gateway.WithConfig(config.FromFile(configPath)), + gateway.WithUser("User1"), + ) + if err != nil { + t.Fatalf("Failed to create new Gateway: %s", err) + } + defer gw.Close() + + nw, err := gw.GetNetwork(channelID) + if err != nil { + t.Fatalf("Failed to get network: %s", err) + } + + contract := nw.GetContract(ccID) + testTransientData(contract, t) +} + func testGateway(gw *gateway.Gateway, t *testing.T) { nw, err := gw.GetNetwork(channelID) if err != nil { @@ -149,6 +171,25 @@ func runContract(contract *gateway.Contract, t *testing.T) { } } +func testTransientData(contract *gateway.Contract, t *testing.T) { + transient := make(map[string][]byte) + transient["result"] = []byte("8500") + + txn, err := contract.CreateTransaction("invoke", gateway.WithTransient(transient)) + if err != nil { + t.Fatalf("Failed to create transaction: %s", err) + } + + result, err := txn.Submit("move", "a", "b", "1") + if err != nil { + t.Fatalf("Failed to submit transaction: %s", err) + } + + if string(result) != "8500" { + t.Fatalf("Incorrect result: %s", string(result)) + } +} + func populateWallet(wallet *gateway.Wallet) error { credPath := filepath.Join( metadata.GetProjectPath(), diff --git a/test/integration/pkg/gateway/gateway_test.go b/test/integration/pkg/gateway/gateway_test.go index 9fd38ed721..a3f2258b96 100644 --- a/test/integration/pkg/gateway/gateway_test.go +++ b/test/integration/pkg/gateway/gateway_test.go @@ -27,3 +27,9 @@ func TestGatewayWithWallet(t *testing.T) { RunWithWallet(t) }) } + +func TestTransientData(t *testing.T) { + t.Run("Base", func(t *testing.T) { + RunWithTransient(t) + }) +}