From f8e170e9537194bd37225b4a8ffe267c3e57daff Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Wed, 16 Feb 2022 13:43:52 -0500 Subject: [PATCH] Build a predictable response body for async "InvokeContract" calls Instead of proxying the response from ethconnect/fabconnect, successful "InvokeContract" calls can return a predictable response body constructed by the Contract Manager. The request ID (which is actually the FireFly operation ID) was the only interesting thing returned in the first place, so starting with just that in the new response body. Signed-off-by: Andrew Richardson --- docs/swagger/swagger.yaml | 15 ++++-- .../route_post_contract_api_invoke.go | 2 +- .../route_post_contract_interface_invoke.go | 2 +- .../apiserver/route_post_contract_invoke.go | 2 +- internal/blockchain/ethereum/ethereum.go | 18 ++----- internal/blockchain/ethereum/ethereum_test.go | 47 +++-------------- internal/blockchain/fabric/fabric.go | 18 ++----- internal/blockchain/fabric/fabric_test.go | 52 ++++--------------- internal/contracts/manager.go | 3 +- internal/contracts/manager_test.go | 8 +-- mocks/blockchainmocks/plugin.go | 19 ++----- pkg/blockchain/plugin.go | 2 +- pkg/fftypes/contracts.go | 4 ++ 13 files changed, 58 insertions(+), 134 deletions(-) diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index e2163e8628..384063a527 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -597,7 +597,10 @@ paths: "200": content: application/json: - schema: {} + schema: + properties: + id: {} + type: object description: Success default: description: "" @@ -2025,7 +2028,10 @@ paths: "200": content: application/json: - schema: {} + schema: + properties: + id: {} + type: object description: Success default: description: "" @@ -2409,7 +2415,10 @@ paths: "200": content: application/json: - schema: {} + schema: + properties: + id: {} + type: object description: Success default: description: "" diff --git a/internal/apiserver/route_post_contract_api_invoke.go b/internal/apiserver/route_post_contract_api_invoke.go index feb8a02957..7d65a4c24d 100644 --- a/internal/apiserver/route_post_contract_api_invoke.go +++ b/internal/apiserver/route_post_contract_api_invoke.go @@ -41,7 +41,7 @@ var postContractAPIInvoke = &oapispec.Route{ Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.ContractCallRequest{} }, JSONInputMask: []string{"Type", "Interface", "Method"}, - JSONOutputValue: func() interface{} { return make(map[string]interface{}) }, + JSONOutputValue: func() interface{} { return &fftypes.ContractCallResponse{} }, JSONOutputCodes: []int{http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { req := r.Input.(*fftypes.ContractCallRequest) diff --git a/internal/apiserver/route_post_contract_interface_invoke.go b/internal/apiserver/route_post_contract_interface_invoke.go index da33222147..725dd010d3 100644 --- a/internal/apiserver/route_post_contract_interface_invoke.go +++ b/internal/apiserver/route_post_contract_interface_invoke.go @@ -41,7 +41,7 @@ var postContractInterfaceInvoke = &oapispec.Route{ Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.ContractCallRequest{} }, JSONInputMask: []string{"Type", "Interface"}, - JSONOutputValue: func() interface{} { return make(map[string]interface{}) }, + JSONOutputValue: func() interface{} { return &fftypes.ContractCallResponse{} }, JSONOutputCodes: []int{http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { req := r.Input.(*fftypes.ContractCallRequest) diff --git a/internal/apiserver/route_post_contract_invoke.go b/internal/apiserver/route_post_contract_invoke.go index 52ebfa111d..1d12f1069c 100644 --- a/internal/apiserver/route_post_contract_invoke.go +++ b/internal/apiserver/route_post_contract_invoke.go @@ -39,7 +39,7 @@ var postContractInvoke = &oapispec.Route{ Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.ContractCallRequest{} }, JSONInputMask: []string{"Type"}, - JSONOutputValue: func() interface{} { return make(map[string]interface{}) }, + JSONOutputValue: func() interface{} { return &fftypes.ContractCallResponse{} }, JSONOutputCodes: []int{http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { req := r.Input.(*fftypes.ContractCallRequest) diff --git a/internal/blockchain/ethereum/ethereum.go b/internal/blockchain/ethereum/ethereum.go index f24e6a1eca..bba7721c53 100644 --- a/internal/blockchain/ethereum/ethereum.go +++ b/internal/blockchain/ethereum/ethereum.go @@ -63,10 +63,6 @@ type eventStreamWebsocket struct { Topic string `json:"topic"` } -type asyncTXSubmission struct { - ID string `json:"id"` -} - type queryOutput struct { Output string `json:"output"` } @@ -537,24 +533,20 @@ func (e *Ethereum) SubmitBatchPin(ctx context.Context, operationID *fftypes.UUID return nil } -func (e *Ethereum) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) { +func (e *Ethereum) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) error { ethereumLocation, err := parseContractLocation(ctx, location) if err != nil { - return nil, err + return err } abi, orderedInput, err := e.prepareRequest(ctx, method, input) if err != nil { - return nil, err + return err } res, err := e.invokeContractMethod(ctx, ethereumLocation.Address, signingKey, abi, operationID.String(), orderedInput) if err != nil || !res.IsSuccess() { - return nil, restclient.WrapRestErr(ctx, res, err, i18n.MsgEthconnectRESTErr) - } - tx := &asyncTXSubmission{} - if err = json.Unmarshal(res.Body(), tx); err != nil { - return nil, err + return restclient.WrapRestErr(ctx, res, err, i18n.MsgEthconnectRESTErr) } - return tx, nil + return nil } func (e *Ethereum) QueryContract(ctx context.Context, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) { diff --git a/internal/blockchain/ethereum/ethereum_test.go b/internal/blockchain/ethereum/ethereum_test.go index 16bb866462..eb6fb86a02 100644 --- a/internal/blockchain/ethereum/ethereum_test.go +++ b/internal/blockchain/ethereum/ethereum_test.go @@ -511,7 +511,7 @@ func TestSubmitBatchPinOK(t *testing.T) { assert.Equal(t, "0x9ffc50ff6bfe4502adc793aea54cc059c5df767cfe444e038eb51c5523097db5", params[1]) assert.Equal(t, ethHexFormatB32(batch.BatchHash), params[2]) assert.Equal(t, "Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD", params[3]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) err := e.SubmitBatchPin(context.Background(), nil, nil, addr, batch) @@ -548,7 +548,7 @@ func TestSubmitBatchEmptyPayloadRef(t *testing.T) { assert.Equal(t, "0x9ffc50ff6bfe4502adc793aea54cc059c5df767cfe444e038eb51c5523097db5", params[1]) assert.Equal(t, ethHexFormatB32(batch.BatchHash), params[2]) assert.Equal(t, "", params[3]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) err := e.SubmitBatchPin(context.Background(), nil, nil, addr, batch) @@ -1521,9 +1521,9 @@ func TestInvokeContractOK(t *testing.T) { assert.Equal(t, "SendTransaction", headers["type"]) assert.Equal(t, float64(1), params[0]) assert.Equal(t, float64(2), params[1]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.NoError(t, err) } @@ -1539,7 +1539,7 @@ func TestInvokeContractAddressNotSet(t *testing.T) { } locationBytes, err := json.Marshal(location) assert.NoError(t, err) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "'address' not set", err) } @@ -1561,9 +1561,9 @@ func TestInvokeContractEthconnectError(t *testing.T) { assert.NoError(t, err) httpmock.RegisterResponder("POST", `http://localhost:12345/`, func(req *http.Request) (*http.Response, error) { - return httpmock.NewJsonResponderOrPanic(400, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(400, "")(req) }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "FF10111", err) } @@ -1590,41 +1590,10 @@ func TestInvokeContractPrepareFail(t *testing.T) { } locationBytes, err := json.Marshal(location) assert.NoError(t, err) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "invalid json", err) } -func TestInvokeContractUnmarshalResponseError(t *testing.T) { - e, cancel := newTestEthereum() - defer cancel() - httpmock.ActivateNonDefault(e.client.GetClient()) - defer httpmock.DeactivateAndReset() - signingKey := ethHexFormatB32(fftypes.NewRandB32()) - location := &Location{ - Address: "0x12345", - } - method := testFFIMethod() - params := map[string]interface{}{ - "x": float64(1), - "y": float64(2), - } - locationBytes, err := json.Marshal(location) - assert.NoError(t, err) - httpmock.RegisterResponder("POST", `http://localhost:12345/`, - func(req *http.Request) (*http.Response, error) { - var body map[string]interface{} - json.NewDecoder(req.Body).Decode(&body) - params := body["params"].([]interface{}) - headers := body["headers"].(map[string]interface{}) - assert.Equal(t, "SendTransaction", headers["type"]) - assert.Equal(t, float64(1), params[0]) - assert.Equal(t, float64(2), params[1]) - return httpmock.NewStringResponder(200, "[definitely not JSON}")(req) - }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) - assert.Regexp(t, "invalid character", err) -} - func TestQueryContractOK(t *testing.T) { e, cancel := newTestEthereum() defer cancel() diff --git a/internal/blockchain/fabric/fabric.go b/internal/blockchain/fabric/fabric.go index 23a9e42ede..554d97d3a5 100644 --- a/internal/blockchain/fabric/fabric.go +++ b/internal/blockchain/fabric/fabric.go @@ -66,10 +66,6 @@ type eventStreamWebsocket struct { Topic string `json:"topic"` } -type asyncTXSubmission struct { - ID string `json:"id"` -} - type fabBatchPinInput struct { Namespace string `json:"namespace"` UUIDs string `json:"uuids"` @@ -553,11 +549,11 @@ func (f *Fabric) SubmitBatchPin(ctx context.Context, operationID *fftypes.UUID, return nil } -func (f *Fabric) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) { +func (f *Fabric) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) error { // All arguments must be JSON serialized args, err := jsonEncodeInput(input) if err != nil { - return nil, i18n.WrapError(ctx, err, i18n.MsgJSONObjectParseFailed, "params") + return i18n.WrapError(ctx, err, i18n.MsgJSONObjectParseFailed, "params") } in := &fabTxNamedInput{ Func: method.Name, @@ -579,18 +575,14 @@ func (f *Fabric) InvokeContract(ctx context.Context, operationID *fftypes.UUID, fabricOnChainLocation, err := parseContractLocation(ctx, location) if err != nil { - return nil, err + return err } res, err := f.invokeContractMethod(ctx, fabricOnChainLocation.Channel, fabricOnChainLocation.Chaincode, signingKey, operationID.String(), in) if err != nil || !res.IsSuccess() { - return nil, restclient.WrapRestErr(ctx, res, err, i18n.MsgFabconnectRESTErr) - } - tx := &asyncTXSubmission{} - if err = json.Unmarshal(res.Body(), tx); err != nil { - return nil, err + return restclient.WrapRestErr(ctx, res, err, i18n.MsgFabconnectRESTErr) } - return tx, nil + return nil } func jsonEncodeInput(params map[string]interface{}) (output map[string]string, err error) { diff --git a/internal/blockchain/fabric/fabric_test.go b/internal/blockchain/fabric/fabric_test.go index 7717ab2bff..5252009bd9 100644 --- a/internal/blockchain/fabric/fabric_test.go +++ b/internal/blockchain/fabric/fabric_test.go @@ -402,7 +402,7 @@ func TestSubmitBatchPinOK(t *testing.T) { assert.Equal(t, "0x9ffc50ff6bfe4502adc793aea54cc059c5df767cfe444e038eb51c5523097db5", (body["args"].([]interface{}))[1]) assert.Equal(t, hexFormatB32(batch.BatchHash), (body["args"].([]interface{}))[2]) assert.Equal(t, "Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD", (body["args"].([]interface{}))[3]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) err := e.SubmitBatchPin(context.Background(), nil, nil, signer, batch) @@ -438,7 +438,7 @@ func TestSubmitBatchEmptyPayloadRef(t *testing.T) { assert.Equal(t, "0x9ffc50ff6bfe4502adc793aea54cc059c5df767cfe444e038eb51c5523097db5", (body["args"].([]interface{}))[1]) assert.Equal(t, hexFormatB32(batch.BatchHash), (body["args"].([]interface{}))[2]) assert.Equal(t, "", (body["args"].([]interface{}))[3]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) err := e.SubmitBatchPin(context.Background(), nil, nil, signer, batch) @@ -1344,9 +1344,9 @@ func TestInvokeContractOK(t *testing.T) { assert.Equal(t, "false", req.URL.Query().Get(defaultPrefixShort+"-sync")) assert.Equal(t, "1", body["args"].(map[string]interface{})["x"]) assert.Equal(t, "2", body["args"].(map[string]interface{})["y"]) - return httpmock.NewJsonResponderOrPanic(200, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(200, "")(req) }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.NoError(t, err) } @@ -1362,7 +1362,7 @@ func TestInvokeContractChaincodeNotSet(t *testing.T) { } locationBytes, err := json.Marshal(location) assert.NoError(t, err) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "FF10310", err) } @@ -1385,46 +1385,12 @@ func TestInvokeContractFabconnectError(t *testing.T) { assert.NoError(t, err) httpmock.RegisterResponder("POST", `http://localhost:12345/transactions`, func(req *http.Request) (*http.Response, error) { - return httpmock.NewJsonResponderOrPanic(400, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(400, "")(req) }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "FF10284", err) } -func TestInvokeContractUnmarshalResponseError(t *testing.T) { - e, cancel := newTestFabric() - defer cancel() - httpmock.ActivateNonDefault(e.client.GetClient()) - defer httpmock.DeactivateAndReset() - signingKey := fftypes.NewRandB32().String() - location := &Location{ - Channel: "firefly", - Chaincode: "simplestorage", - } - method := testFFIMethod() - params := map[string]interface{}{ - "x": float64(1), - "y": float64(2), - } - locationBytes, err := json.Marshal(location) - assert.NoError(t, err) - httpmock.RegisterResponder("POST", `http://localhost:12345/transactions`, - func(req *http.Request) (*http.Response, error) { - var body map[string]interface{} - json.NewDecoder(req.Body).Decode(&body) - - assert.Equal(t, signingKey, req.URL.Query().Get(defaultPrefixShort+"-signer")) - assert.Equal(t, "firefly", req.URL.Query().Get(defaultPrefixShort+"-channel")) - assert.Equal(t, "simplestorage", req.URL.Query().Get(defaultPrefixShort+"-chaincode")) - assert.Equal(t, "false", req.URL.Query().Get(defaultPrefixShort+"-sync")) - assert.Equal(t, "1", body["args"].(map[string]interface{})["x"]) - assert.Equal(t, "2", body["args"].(map[string]interface{})["y"]) - return httpmock.NewStringResponder(200, "[definitely not JSON}")(req) - }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) - assert.Regexp(t, "invalid character", err) -} - func TestQueryContractOK(t *testing.T) { e, cancel := newTestFabric() defer cancel() @@ -1489,9 +1455,9 @@ func TestInvokeJSONEncodeParamsError(t *testing.T) { assert.NoError(t, err) httpmock.RegisterResponder("POST", `http://localhost:12345/transactions`, func(req *http.Request) (*http.Response, error) { - return httpmock.NewJsonResponderOrPanic(400, asyncTXSubmission{})(req) + return httpmock.NewJsonResponderOrPanic(400, "")(req) }) - _, err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) + err = e.InvokeContract(context.Background(), nil, signingKey, fftypes.JSONAnyPtrBytes(locationBytes), method, params) assert.Regexp(t, "FF10151", err) } diff --git a/internal/contracts/manager.go b/internal/contracts/manager.go index 2ac6358587..266edd2ac6 100644 --- a/internal/contracts/manager.go +++ b/internal/contracts/manager.go @@ -203,7 +203,8 @@ func (cm *contractManager) InvokeContract(ctx context.Context, ns string, req *f switch req.Type { case fftypes.CallTypeInvoke: - res, err = cm.blockchain.InvokeContract(ctx, op.ID, req.Key, req.Location, req.Method, req.Input) + err = cm.blockchain.InvokeContract(ctx, op.ID, req.Key, req.Location, req.Method, req.Input) + res = &fftypes.ContractCallResponse{ID: op.ID} case fftypes.CallTypeQuery: res, err = cm.blockchain.QueryContract(ctx, req.Location, req.Method, req.Input) default: diff --git a/internal/contracts/manager_test.go b/internal/contracts/manager_test.go index 477cf498fc..3886d4f618 100644 --- a/internal/contracts/manager_test.go +++ b/internal/contracts/manager_test.go @@ -996,7 +996,7 @@ func TestInvokeContract(t *testing.T) { mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool { return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain" })).Return(nil) - mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(struct{}{}, nil) + mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(nil) _, err := cm.InvokeContract(context.Background(), "ns1", req) @@ -1030,7 +1030,7 @@ func TestInvokeContractFail(t *testing.T) { mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool { return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain" })).Return(nil) - mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(nil, fmt.Errorf("pop")) + mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(fmt.Errorf("pop")) mth.On("WriteOperationFailure", mock.Anything, mock.Anything, fmt.Errorf("pop")) _, err := cm.InvokeContract(context.Background(), "ns1", req) @@ -1070,7 +1070,7 @@ func TestInvokeContractFailResolve(t *testing.T) { } mim.On("ResolveSigningKey", mock.Anything, "").Return("key-resolved", nil) - mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(struct{}{}, nil) + mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(nil) _, err := cm.InvokeContract(context.Background(), "ns1", req) @@ -1389,7 +1389,7 @@ func TestInvokeContractAPI(t *testing.T) { mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool { return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain" })).Return(nil) - mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, mock.AnythingOfType("*fftypes.FFIMethod"), req.Input).Return(struct{}{}, nil) + mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, mock.AnythingOfType("*fftypes.FFIMethod"), req.Input).Return(nil) _, err := cm.InvokeContractAPI(context.Background(), "ns1", "banana", "peel", req) diff --git a/mocks/blockchainmocks/plugin.go b/mocks/blockchainmocks/plugin.go index 17c1a0ec67..e7f4cf56ab 100644 --- a/mocks/blockchainmocks/plugin.go +++ b/mocks/blockchainmocks/plugin.go @@ -105,26 +105,17 @@ func (_m *Plugin) InitPrefix(prefix config.Prefix) { } // InvokeContract provides a mock function with given fields: ctx, operationID, signingKey, location, method, input -func (_m *Plugin) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) { +func (_m *Plugin) InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) error { ret := _m.Called(ctx, operationID, signingKey, location, method, input) - var r0 interface{} - if rf, ok := ret.Get(0).(func(context.Context, *fftypes.UUID, string, *fftypes.JSONAny, *fftypes.FFIMethod, map[string]interface{}) interface{}); ok { + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *fftypes.UUID, string, *fftypes.JSONAny, *fftypes.FFIMethod, map[string]interface{}) error); ok { r0 = rf(ctx, operationID, signingKey, location, method, input) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *fftypes.UUID, string, *fftypes.JSONAny, *fftypes.FFIMethod, map[string]interface{}) error); ok { - r1 = rf(ctx, operationID, signingKey, location, method, input) - } else { - r1 = ret.Error(1) + r0 = ret.Error(0) } - return r0, r1 + return r0 } // Name provides a mock function with given fields: diff --git a/pkg/blockchain/plugin.go b/pkg/blockchain/plugin.go index eba9bed8aa..3a7d04825f 100644 --- a/pkg/blockchain/plugin.go +++ b/pkg/blockchain/plugin.go @@ -48,7 +48,7 @@ type Plugin interface { SubmitBatchPin(ctx context.Context, operationID *fftypes.UUID, ledgerID *fftypes.UUID, signingKey string, batch *BatchPin) error // InvokeContract submits a new transaction to be executed by custom on-chain logic - InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) + InvokeContract(ctx context.Context, operationID *fftypes.UUID, signingKey string, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) error // QueryContract executes a method via custom on-chain logic and returns the result QueryContract(ctx context.Context, location *fftypes.JSONAny, method *fftypes.FFIMethod, input map[string]interface{}) (interface{}, error) diff --git a/pkg/fftypes/contracts.go b/pkg/fftypes/contracts.go index 9c2c4df451..43b46f964b 100644 --- a/pkg/fftypes/contracts.go +++ b/pkg/fftypes/contracts.go @@ -37,6 +37,10 @@ type ContractCallRequest struct { Input map[string]interface{} `json:"input"` } +type ContractCallResponse struct { + ID *UUID `json:"id"` +} + type ContractSubscribeRequest struct { Interface *UUID `json:"interface,omitempty"` Location *JSONAny `json:"location,omitempty"`