This is an automated email from the ASF dual-hosted git repository.

littlecui pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/incubator-servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 47203c7  SC-49 Pact broker module for consumer-driven contract testing 
(#220)
47203c7 is described below

commit 47203c76d5b4b1b5cb88f1d92374cc2d6ea3c3f4
Author: Ganesha Upadhyaya <[email protected]>
AuthorDate: Tue Feb 27 20:29:56 2018 -0600

    SC-49 Pact broker module for consumer-driven contract testing (#220)
    
    * pact broker implementation as sc module
    
    * fixing bugs
    
    * adding some tests
    
    * updating imports and fixing the cache invoke
    
    * updating the license info
    
    * reverting an unnecessary change
    
    * updating broker to the latest changes and fixing the broken integration 
test
    
    * updating PR change requests
---
 server/bootstrap/bootstrap.go         |   3 +
 server/broker/README.md               |  98 ++++
 server/broker/broker.go               |  29 ++
 server/broker/broker.pb.go            | 950 ++++++++++++++++++++++++++++++++++
 server/broker/broker.proto            | 158 ++++++
 server/broker/broker_key_generator.go | 200 +++++++
 server/broker/controller.go           | 191 +++++++
 server/broker/service.go              | 874 +++++++++++++++++++++++++++++++
 server/broker/service_test.go         | 200 +++++++
 server/broker/store.go                | 156 ++++++
 server/broker/util.go                 | 680 ++++++++++++++++++++++++
 server/rest/controller/rest_util.go   |  12 +
 12 files changed, 3551 insertions(+)

diff --git a/server/bootstrap/bootstrap.go b/server/bootstrap/bootstrap.go
index 058d034..1bd7a5a 100644
--- a/server/bootstrap/bootstrap.go
+++ b/server/bootstrap/bootstrap.go
@@ -45,6 +45,9 @@ import _ 
"github.com/apache/incubator-servicecomb-service-center/server/plugin/i
 // module
 import _ "github.com/apache/incubator-servicecomb-service-center/server/govern"
 
+// module
+import _ "github.com/apache/incubator-servicecomb-service-center/server/broker"
+
 import (
        "github.com/apache/incubator-servicecomb-service-center/pkg/util"
        
"github.com/apache/incubator-servicecomb-service-center/server/handler/auth"
diff --git a/server/broker/README.md b/server/broker/README.md
new file mode 100644
index 0000000..9f57908
--- /dev/null
+++ b/server/broker/README.md
@@ -0,0 +1,98 @@
+# Pact Broker Module
+
+Pact broker module enables consumer-driven contract testing in service-center.
+
+## Pact broker services
+
+* Consumer microservices can publish pact.
+
+```
+PUT /pacts/provider/:providerId/consumer/:consumerId/version/:number
+'{
+       "provider" : "",
+       "consumer" : "",
+       ...
+       
+}'
+```
+
+* Provider microservices can retrieve pacts published by consumer 
microservices, verify the pacts, and publish the verification results.
+       
+       1. Retrieving the information about the pacts associated with a provider
+
+```
+GET /pacts/provider/:providerId/latest
+
+Response:
+{
+       "_links" : {
+               "pacts" : [
+                       {
+                               "href" : 
"/pacts/provider/:providerId/consumer/:consumerId/version/:number"
+                               "name" : "Pact between consumerId and 
providerId with version number"
+                       }
+               ]
+       }
+}
+```
+
+       2. Retrieving the actual pact between a consumer and provider for 
verification
+
+```
+GET /pacts/provider/:providerId/consumer/:consumerId/version/:number
+Response:
+{
+       "pact" : []byte
+}
+```
+
+       3. Publishing the pact verification result to the broker
+
+```
+POST 
/pacts/provider/:providerId/consumer/:consumerId/pact-version/:number/verification-results
+'{
+       "success" : true
+       "providerApplicationVersion" : "0.0.1"
+}'
+
+Response:
+{
+       "confirmation" : {
+               "providerName" : ""
+               "providerApplicationVersion" : "0.0.1"
+               "success" : true
+               "verificationDate" : ""
+       }
+}
+```
+
+* Consumer microservices can retrieve the verification results published by 
the providers.
+
+```
+GET /verification-results/consumer/:consumerId/version/:version/latest
+
+Response:
+{
+       "result" : {
+               "success" : true
+               "providerSummary" : {
+                       "successful" : [
+                       ]
+                       "failed" : [
+                       ]
+                       "unknown" : [
+                       ]
+               }
+               "_embedded" :  {
+                       "verificationResults" : [
+                               {
+                                       "providerName" : ""
+                                       "providerApplicationVersion" : ""
+                                       "success" : true
+                                       "verificationDate" : "" 
+                               }
+                       ]
+               }
+       }
+}
+``` 
\ No newline at end of file
diff --git a/server/broker/broker.go b/server/broker/broker.go
new file mode 100644
index 0000000..fc807be
--- /dev/null
+++ b/server/broker/broker.go
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       roa "github.com/apache/incubator-servicecomb-service-center/pkg/rest"
+)
+
+func init() {
+       registerREST()
+}
+
+func registerREST() {
+       roa.RegisterServent(&BrokerController{})
+}
diff --git a/server/broker/broker.pb.go b/server/broker/broker.pb.go
new file mode 100644
index 0000000..0dffd1c
--- /dev/null
+++ b/server/broker/broker.pb.go
@@ -0,0 +1,950 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: server/broker/broker.proto
+
+/*
+Package broker is a generated protocol buffer package.
+
+It is generated from these files:
+       server/broker/broker.proto
+
+It has these top-level messages:
+       Participant
+       Version
+       Pact
+       PactVersion
+       Tag
+       PublishPactRequest
+       PublishPactResponse
+       GetAllProviderPactsRequest
+       ConsumerInfo
+       Links
+       GetAllProviderPactsResponse
+       GetProviderConsumerVersionPactRequest
+       GetProviderConsumerVersionPactResponse
+       Verification
+       VerificationSummary
+       VerificationDetail
+       VerificationDetails
+       VerificationResult
+       PublishVerificationRequest
+       PublishVerificationResponse
+       RetrieveVerificationRequest
+       RetrieveVerificationResponse
+       BaseBrokerRequest
+       BrokerAPIInfoEntry
+       BrokerHomeResponse
+*/
+package broker
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import services 
"github.com/apache/incubator-servicecomb-service-center/server/core/proto"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Participant struct {
+       Id          int32  `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
+       AppId       string `protobuf:"bytes,2,opt,name=appId" 
json:"appId,omitempty"`
+       ServiceName string `protobuf:"bytes,3,opt,name=serviceName" 
json:"serviceName,omitempty"`
+}
+
+func (m *Participant) Reset()                    { *m = Participant{} }
+func (m *Participant) String() string            { return 
proto.CompactTextString(m) }
+func (*Participant) ProtoMessage()               {}
+func (*Participant) Descriptor() ([]byte, []int) { return fileDescriptor0, 
[]int{0} }
+
+func (m *Participant) GetId() int32 {
+       if m != nil {
+               return m.Id
+       }
+       return 0
+}
+
+func (m *Participant) GetAppId() string {
+       if m != nil {
+               return m.AppId
+       }
+       return ""
+}
+
+func (m *Participant) GetServiceName() string {
+       if m != nil {
+               return m.ServiceName
+       }
+       return ""
+}
+
+type Version struct {
+       Id            int32  `protobuf:"varint,1,opt,name=id" 
json:"id,omitempty"`
+       Number        string `protobuf:"bytes,2,opt,name=number" 
json:"number,omitempty"`
+       ParticipantId int32  `protobuf:"varint,3,opt,name=participantId" 
json:"participantId,omitempty"`
+       Order         int32  `protobuf:"varint,4,opt,name=order" 
json:"order,omitempty"`
+}
+
+func (m *Version) Reset()                    { *m = Version{} }
+func (m *Version) String() string            { return 
proto.CompactTextString(m) }
+func (*Version) ProtoMessage()               {}
+func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, 
[]int{1} }
+
+func (m *Version) GetId() int32 {
+       if m != nil {
+               return m.Id
+       }
+       return 0
+}
+
+func (m *Version) GetNumber() string {
+       if m != nil {
+               return m.Number
+       }
+       return ""
+}
+
+func (m *Version) GetParticipantId() int32 {
+       if m != nil {
+               return m.ParticipantId
+       }
+       return 0
+}
+
+func (m *Version) GetOrder() int32 {
+       if m != nil {
+               return m.Order
+       }
+       return 0
+}
+
+type Pact struct {
+       Id                    int32  `protobuf:"varint,1,opt,name=id" 
json:"id,omitempty"`
+       ConsumerParticipantId int32  
`protobuf:"varint,2,opt,name=consumerParticipantId" 
json:"consumerParticipantId,omitempty"`
+       ProviderParticipantId int32  
`protobuf:"varint,3,opt,name=providerParticipantId" 
json:"providerParticipantId,omitempty"`
+       Sha                   []byte `protobuf:"bytes,4,opt,name=sha,proto3" 
json:"sha,omitempty"`
+       Content               []byte 
`protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"`
+}
+
+func (m *Pact) Reset()                    { *m = Pact{} }
+func (m *Pact) String() string            { return proto.CompactTextString(m) }
+func (*Pact) ProtoMessage()               {}
+func (*Pact) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *Pact) GetId() int32 {
+       if m != nil {
+               return m.Id
+       }
+       return 0
+}
+
+func (m *Pact) GetConsumerParticipantId() int32 {
+       if m != nil {
+               return m.ConsumerParticipantId
+       }
+       return 0
+}
+
+func (m *Pact) GetProviderParticipantId() int32 {
+       if m != nil {
+               return m.ProviderParticipantId
+       }
+       return 0
+}
+
+func (m *Pact) GetSha() []byte {
+       if m != nil {
+               return m.Sha
+       }
+       return nil
+}
+
+func (m *Pact) GetContent() []byte {
+       if m != nil {
+               return m.Content
+       }
+       return nil
+}
+
+type PactVersion struct {
+       Id                    int32 `protobuf:"varint,1,opt,name=id" 
json:"id,omitempty"`
+       VersionId             int32 `protobuf:"varint,2,opt,name=versionId" 
json:"versionId,omitempty"`
+       PactId                int32 `protobuf:"varint,3,opt,name=pactId" 
json:"pactId,omitempty"`
+       ProviderParticipantId int32 
`protobuf:"varint,4,opt,name=providerParticipantId" 
json:"providerParticipantId,omitempty"`
+}
+
+func (m *PactVersion) Reset()                    { *m = PactVersion{} }
+func (m *PactVersion) String() string            { return 
proto.CompactTextString(m) }
+func (*PactVersion) ProtoMessage()               {}
+func (*PactVersion) Descriptor() ([]byte, []int) { return fileDescriptor0, 
[]int{3} }
+
+func (m *PactVersion) GetId() int32 {
+       if m != nil {
+               return m.Id
+       }
+       return 0
+}
+
+func (m *PactVersion) GetVersionId() int32 {
+       if m != nil {
+               return m.VersionId
+       }
+       return 0
+}
+
+func (m *PactVersion) GetPactId() int32 {
+       if m != nil {
+               return m.PactId
+       }
+       return 0
+}
+
+func (m *PactVersion) GetProviderParticipantId() int32 {
+       if m != nil {
+               return m.ProviderParticipantId
+       }
+       return 0
+}
+
+type Tag struct {
+       Name      string `protobuf:"bytes,1,opt,name=name" 
json:"name,omitempty"`
+       VersionId int32  `protobuf:"varint,2,opt,name=versionId" 
json:"versionId,omitempty"`
+}
+
+func (m *Tag) Reset()                    { *m = Tag{} }
+func (m *Tag) String() string            { return proto.CompactTextString(m) }
+func (*Tag) ProtoMessage()               {}
+func (*Tag) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *Tag) GetName() string {
+       if m != nil {
+               return m.Name
+       }
+       return ""
+}
+
+func (m *Tag) GetVersionId() int32 {
+       if m != nil {
+               return m.VersionId
+       }
+       return 0
+}
+
+type PublishPactRequest struct {
+       ProviderId string `protobuf:"bytes,1,opt,name=providerId" 
json:"providerId,omitempty"`
+       ConsumerId string `protobuf:"bytes,2,opt,name=consumerId" 
json:"consumerId,omitempty"`
+       Version    string `protobuf:"bytes,3,opt,name=version" 
json:"version,omitempty"`
+       Pact       []byte `protobuf:"bytes,4,opt,name=pact,proto3" 
json:"pact,omitempty"`
+}
+
+func (m *PublishPactRequest) Reset()                    { *m = 
PublishPactRequest{} }
+func (m *PublishPactRequest) String() string            { return 
proto.CompactTextString(m) }
+func (*PublishPactRequest) ProtoMessage()               {}
+func (*PublishPactRequest) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{5} }
+
+func (m *PublishPactRequest) GetProviderId() string {
+       if m != nil {
+               return m.ProviderId
+       }
+       return ""
+}
+
+func (m *PublishPactRequest) GetConsumerId() string {
+       if m != nil {
+               return m.ConsumerId
+       }
+       return ""
+}
+
+func (m *PublishPactRequest) GetVersion() string {
+       if m != nil {
+               return m.Version
+       }
+       return ""
+}
+
+func (m *PublishPactRequest) GetPact() []byte {
+       if m != nil {
+               return m.Pact
+       }
+       return nil
+}
+
+type PublishPactResponse struct {
+       Response *services.Response `protobuf:"bytes,1,opt,name=response" 
json:"response,omitempty"`
+}
+
+func (m *PublishPactResponse) Reset()                    { *m = 
PublishPactResponse{} }
+func (m *PublishPactResponse) String() string            { return 
proto.CompactTextString(m) }
+func (*PublishPactResponse) ProtoMessage()               {}
+func (*PublishPactResponse) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{6} }
+
+func (m *PublishPactResponse) GetResponse() *services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+type GetAllProviderPactsRequest struct {
+       ProviderId string             `protobuf:"bytes,1,opt,name=providerId" 
json:"providerId,omitempty"`
+       BaseUrl    *BaseBrokerRequest `protobuf:"bytes,2,opt,name=baseUrl" 
json:"baseUrl,omitempty"`
+}
+
+func (m *GetAllProviderPactsRequest) Reset()                    { *m = 
GetAllProviderPactsRequest{} }
+func (m *GetAllProviderPactsRequest) String() string            { return 
proto.CompactTextString(m) }
+func (*GetAllProviderPactsRequest) ProtoMessage()               {}
+func (*GetAllProviderPactsRequest) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{7} }
+
+func (m *GetAllProviderPactsRequest) GetProviderId() string {
+       if m != nil {
+               return m.ProviderId
+       }
+       return ""
+}
+
+func (m *GetAllProviderPactsRequest) GetBaseUrl() *BaseBrokerRequest {
+       if m != nil {
+               return m.BaseUrl
+       }
+       return nil
+}
+
+type ConsumerInfo struct {
+       Href string `protobuf:"bytes,1,opt,name=href" json:"href,omitempty"`
+       Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
+}
+
+func (m *ConsumerInfo) Reset()                    { *m = ConsumerInfo{} }
+func (m *ConsumerInfo) String() string            { return 
proto.CompactTextString(m) }
+func (*ConsumerInfo) ProtoMessage()               {}
+func (*ConsumerInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, 
[]int{8} }
+
+func (m *ConsumerInfo) GetHref() string {
+       if m != nil {
+               return m.Href
+       }
+       return ""
+}
+
+func (m *ConsumerInfo) GetName() string {
+       if m != nil {
+               return m.Name
+       }
+       return ""
+}
+
+type Links struct {
+       Pacts []*ConsumerInfo `protobuf:"bytes,1,rep,name=pacts" 
json:"pacts,omitempty"`
+}
+
+func (m *Links) Reset()                    { *m = Links{} }
+func (m *Links) String() string            { return proto.CompactTextString(m) 
}
+func (*Links) ProtoMessage()               {}
+func (*Links) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+
+func (m *Links) GetPacts() []*ConsumerInfo {
+       if m != nil {
+               return m.Pacts
+       }
+       return nil
+}
+
+type GetAllProviderPactsResponse struct {
+       Response *services.Response `protobuf:"bytes,1,opt,name=response" 
json:"response,omitempty"`
+       XLinks   *Links             
`protobuf:"bytes,2,opt,name=_links,json=Links" json:"_links,omitempty"`
+}
+
+func (m *GetAllProviderPactsResponse) Reset()                    { *m = 
GetAllProviderPactsResponse{} }
+func (m *GetAllProviderPactsResponse) String() string            { return 
proto.CompactTextString(m) }
+func (*GetAllProviderPactsResponse) ProtoMessage()               {}
+func (*GetAllProviderPactsResponse) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{10} }
+
+func (m *GetAllProviderPactsResponse) GetResponse() *services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+func (m *GetAllProviderPactsResponse) GetXLinks() *Links {
+       if m != nil {
+               return m.XLinks
+       }
+       return nil
+}
+
+type GetProviderConsumerVersionPactRequest struct {
+       ProviderId string             `protobuf:"bytes,1,opt,name=providerId" 
json:"providerId,omitempty"`
+       ConsumerId string             `protobuf:"bytes,2,opt,name=consumerId" 
json:"consumerId,omitempty"`
+       Version    string             `protobuf:"bytes,3,opt,name=version" 
json:"version,omitempty"`
+       BaseUrl    *BaseBrokerRequest `protobuf:"bytes,4,opt,name=baseUrl" 
json:"baseUrl,omitempty"`
+}
+
+func (m *GetProviderConsumerVersionPactRequest) Reset()         { *m = 
GetProviderConsumerVersionPactRequest{} }
+func (m *GetProviderConsumerVersionPactRequest) String() string { return 
proto.CompactTextString(m) }
+func (*GetProviderConsumerVersionPactRequest) ProtoMessage()    {}
+func (*GetProviderConsumerVersionPactRequest) Descriptor() ([]byte, []int) {
+       return fileDescriptor0, []int{11}
+}
+
+func (m *GetProviderConsumerVersionPactRequest) GetProviderId() string {
+       if m != nil {
+               return m.ProviderId
+       }
+       return ""
+}
+
+func (m *GetProviderConsumerVersionPactRequest) GetConsumerId() string {
+       if m != nil {
+               return m.ConsumerId
+       }
+       return ""
+}
+
+func (m *GetProviderConsumerVersionPactRequest) GetVersion() string {
+       if m != nil {
+               return m.Version
+       }
+       return ""
+}
+
+func (m *GetProviderConsumerVersionPactRequest) GetBaseUrl() 
*BaseBrokerRequest {
+       if m != nil {
+               return m.BaseUrl
+       }
+       return nil
+}
+
+type GetProviderConsumerVersionPactResponse struct {
+       Response *services.Response `protobuf:"bytes,1,opt,name=response" 
json:"response,omitempty"`
+       Pact     []byte             `protobuf:"bytes,2,opt,name=pact,proto3" 
json:"pact,omitempty"`
+}
+
+func (m *GetProviderConsumerVersionPactResponse) Reset() {
+       *m = GetProviderConsumerVersionPactResponse{}
+}
+func (m *GetProviderConsumerVersionPactResponse) String() string { return 
proto.CompactTextString(m) }
+func (*GetProviderConsumerVersionPactResponse) ProtoMessage()    {}
+func (*GetProviderConsumerVersionPactResponse) Descriptor() ([]byte, []int) {
+       return fileDescriptor0, []int{12}
+}
+
+func (m *GetProviderConsumerVersionPactResponse) GetResponse() 
*services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+func (m *GetProviderConsumerVersionPactResponse) GetPact() []byte {
+       if m != nil {
+               return m.Pact
+       }
+       return nil
+}
+
+type Verification struct {
+       Id               int32  `protobuf:"varint,1,opt,name=id" 
json:"id,omitempty"`
+       Number           int32  `protobuf:"varint,2,opt,name=number" 
json:"number,omitempty"`
+       PactVersionId    int32  `protobuf:"varint,3,opt,name=pactVersionId" 
json:"pactVersionId,omitempty"`
+       Success          bool   `protobuf:"varint,4,opt,name=success" 
json:"success,omitempty"`
+       ProviderVersion  string `protobuf:"bytes,5,opt,name=providerVersion" 
json:"providerVersion,omitempty"`
+       BuildUrl         string `protobuf:"bytes,6,opt,name=buildUrl" 
json:"buildUrl,omitempty"`
+       VerificationDate string `protobuf:"bytes,7,opt,name=verificationDate" 
json:"verificationDate,omitempty"`
+}
+
+func (m *Verification) Reset()                    { *m = Verification{} }
+func (m *Verification) String() string            { return 
proto.CompactTextString(m) }
+func (*Verification) ProtoMessage()               {}
+func (*Verification) Descriptor() ([]byte, []int) { return fileDescriptor0, 
[]int{13} }
+
+func (m *Verification) GetId() int32 {
+       if m != nil {
+               return m.Id
+       }
+       return 0
+}
+
+func (m *Verification) GetNumber() int32 {
+       if m != nil {
+               return m.Number
+       }
+       return 0
+}
+
+func (m *Verification) GetPactVersionId() int32 {
+       if m != nil {
+               return m.PactVersionId
+       }
+       return 0
+}
+
+func (m *Verification) GetSuccess() bool {
+       if m != nil {
+               return m.Success
+       }
+       return false
+}
+
+func (m *Verification) GetProviderVersion() string {
+       if m != nil {
+               return m.ProviderVersion
+       }
+       return ""
+}
+
+func (m *Verification) GetBuildUrl() string {
+       if m != nil {
+               return m.BuildUrl
+       }
+       return ""
+}
+
+func (m *Verification) GetVerificationDate() string {
+       if m != nil {
+               return m.VerificationDate
+       }
+       return ""
+}
+
+type VerificationSummary struct {
+       Successful []string `protobuf:"bytes,1,rep,name=successful" 
json:"successful,omitempty"`
+       Failed     []string `protobuf:"bytes,2,rep,name=failed" 
json:"failed,omitempty"`
+       Unknown    []string `protobuf:"bytes,3,rep,name=unknown" 
json:"unknown,omitempty"`
+}
+
+func (m *VerificationSummary) Reset()                    { *m = 
VerificationSummary{} }
+func (m *VerificationSummary) String() string            { return 
proto.CompactTextString(m) }
+func (*VerificationSummary) ProtoMessage()               {}
+func (*VerificationSummary) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{14} }
+
+func (m *VerificationSummary) GetSuccessful() []string {
+       if m != nil {
+               return m.Successful
+       }
+       return nil
+}
+
+func (m *VerificationSummary) GetFailed() []string {
+       if m != nil {
+               return m.Failed
+       }
+       return nil
+}
+
+func (m *VerificationSummary) GetUnknown() []string {
+       if m != nil {
+               return m.Unknown
+       }
+       return nil
+}
+
+type VerificationDetail struct {
+       ProviderName               string 
`protobuf:"bytes,1,opt,name=providerName" json:"providerName,omitempty"`
+       ProviderApplicationVersion string 
`protobuf:"bytes,2,opt,name=providerApplicationVersion" 
json:"providerApplicationVersion,omitempty"`
+       Success                    bool   `protobuf:"varint,3,opt,name=success" 
json:"success,omitempty"`
+       VerificationDate           string 
`protobuf:"bytes,4,opt,name=verificationDate" json:"verificationDate,omitempty"`
+}
+
+func (m *VerificationDetail) Reset()                    { *m = 
VerificationDetail{} }
+func (m *VerificationDetail) String() string            { return 
proto.CompactTextString(m) }
+func (*VerificationDetail) ProtoMessage()               {}
+func (*VerificationDetail) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{15} }
+
+func (m *VerificationDetail) GetProviderName() string {
+       if m != nil {
+               return m.ProviderName
+       }
+       return ""
+}
+
+func (m *VerificationDetail) GetProviderApplicationVersion() string {
+       if m != nil {
+               return m.ProviderApplicationVersion
+       }
+       return ""
+}
+
+func (m *VerificationDetail) GetSuccess() bool {
+       if m != nil {
+               return m.Success
+       }
+       return false
+}
+
+func (m *VerificationDetail) GetVerificationDate() string {
+       if m != nil {
+               return m.VerificationDate
+       }
+       return ""
+}
+
+type VerificationDetails struct {
+       VerificationResults []*VerificationDetail 
`protobuf:"bytes,1,rep,name=verificationResults" 
json:"verificationResults,omitempty"`
+}
+
+func (m *VerificationDetails) Reset()                    { *m = 
VerificationDetails{} }
+func (m *VerificationDetails) String() string            { return 
proto.CompactTextString(m) }
+func (*VerificationDetails) ProtoMessage()               {}
+func (*VerificationDetails) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{16} }
+
+func (m *VerificationDetails) GetVerificationResults() []*VerificationDetail {
+       if m != nil {
+               return m.VerificationResults
+       }
+       return nil
+}
+
+type VerificationResult struct {
+       Success         bool                 
`protobuf:"varint,1,opt,name=success" json:"success,omitempty"`
+       ProviderSummary *VerificationSummary 
`protobuf:"bytes,2,opt,name=providerSummary" json:"providerSummary,omitempty"`
+       XEmbedded       *VerificationDetails 
`protobuf:"bytes,3,opt,name=_embedded,json=Embedded" json:"_embedded,omitempty"`
+}
+
+func (m *VerificationResult) Reset()                    { *m = 
VerificationResult{} }
+func (m *VerificationResult) String() string            { return 
proto.CompactTextString(m) }
+func (*VerificationResult) ProtoMessage()               {}
+func (*VerificationResult) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{17} }
+
+func (m *VerificationResult) GetSuccess() bool {
+       if m != nil {
+               return m.Success
+       }
+       return false
+}
+
+func (m *VerificationResult) GetProviderSummary() *VerificationSummary {
+       if m != nil {
+               return m.ProviderSummary
+       }
+       return nil
+}
+
+func (m *VerificationResult) GetXEmbedded() *VerificationDetails {
+       if m != nil {
+               return m.XEmbedded
+       }
+       return nil
+}
+
+type PublishVerificationRequest struct {
+       ProviderId                 string 
`protobuf:"bytes,1,opt,name=providerId" json:"providerId,omitempty"`
+       ConsumerId                 string 
`protobuf:"bytes,2,opt,name=consumerId" json:"consumerId,omitempty"`
+       PactId                     int32  `protobuf:"varint,3,opt,name=pactId" 
json:"pactId,omitempty"`
+       Success                    bool   `protobuf:"varint,4,opt,name=success" 
json:"success,omitempty"`
+       ProviderApplicationVersion string 
`protobuf:"bytes,5,opt,name=providerApplicationVersion" 
json:"providerApplicationVersion,omitempty"`
+}
+
+func (m *PublishVerificationRequest) Reset()                    { *m = 
PublishVerificationRequest{} }
+func (m *PublishVerificationRequest) String() string            { return 
proto.CompactTextString(m) }
+func (*PublishVerificationRequest) ProtoMessage()               {}
+func (*PublishVerificationRequest) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{18} }
+
+func (m *PublishVerificationRequest) GetProviderId() string {
+       if m != nil {
+               return m.ProviderId
+       }
+       return ""
+}
+
+func (m *PublishVerificationRequest) GetConsumerId() string {
+       if m != nil {
+               return m.ConsumerId
+       }
+       return ""
+}
+
+func (m *PublishVerificationRequest) GetPactId() int32 {
+       if m != nil {
+               return m.PactId
+       }
+       return 0
+}
+
+func (m *PublishVerificationRequest) GetSuccess() bool {
+       if m != nil {
+               return m.Success
+       }
+       return false
+}
+
+func (m *PublishVerificationRequest) GetProviderApplicationVersion() string {
+       if m != nil {
+               return m.ProviderApplicationVersion
+       }
+       return ""
+}
+
+type PublishVerificationResponse struct {
+       Response     *services.Response  `protobuf:"bytes,1,opt,name=response" 
json:"response,omitempty"`
+       Confirmation *VerificationDetail 
`protobuf:"bytes,2,opt,name=confirmation" json:"confirmation,omitempty"`
+}
+
+func (m *PublishVerificationResponse) Reset()                    { *m = 
PublishVerificationResponse{} }
+func (m *PublishVerificationResponse) String() string            { return 
proto.CompactTextString(m) }
+func (*PublishVerificationResponse) ProtoMessage()               {}
+func (*PublishVerificationResponse) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{19} }
+
+func (m *PublishVerificationResponse) GetResponse() *services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+func (m *PublishVerificationResponse) GetConfirmation() *VerificationDetail {
+       if m != nil {
+               return m.Confirmation
+       }
+       return nil
+}
+
+type RetrieveVerificationRequest struct {
+       ConsumerId      string `protobuf:"bytes,1,opt,name=consumerId" 
json:"consumerId,omitempty"`
+       ConsumerVersion string `protobuf:"bytes,2,opt,name=consumerVersion" 
json:"consumerVersion,omitempty"`
+}
+
+func (m *RetrieveVerificationRequest) Reset()                    { *m = 
RetrieveVerificationRequest{} }
+func (m *RetrieveVerificationRequest) String() string            { return 
proto.CompactTextString(m) }
+func (*RetrieveVerificationRequest) ProtoMessage()               {}
+func (*RetrieveVerificationRequest) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{20} }
+
+func (m *RetrieveVerificationRequest) GetConsumerId() string {
+       if m != nil {
+               return m.ConsumerId
+       }
+       return ""
+}
+
+func (m *RetrieveVerificationRequest) GetConsumerVersion() string {
+       if m != nil {
+               return m.ConsumerVersion
+       }
+       return ""
+}
+
+type RetrieveVerificationResponse struct {
+       Response *services.Response  `protobuf:"bytes,1,opt,name=response" 
json:"response,omitempty"`
+       Result   *VerificationResult `protobuf:"bytes,2,opt,name=result" 
json:"result,omitempty"`
+}
+
+func (m *RetrieveVerificationResponse) Reset()                    { *m = 
RetrieveVerificationResponse{} }
+func (m *RetrieveVerificationResponse) String() string            { return 
proto.CompactTextString(m) }
+func (*RetrieveVerificationResponse) ProtoMessage()               {}
+func (*RetrieveVerificationResponse) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{21} }
+
+func (m *RetrieveVerificationResponse) GetResponse() *services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+func (m *RetrieveVerificationResponse) GetResult() *VerificationResult {
+       if m != nil {
+               return m.Result
+       }
+       return nil
+}
+
+type BaseBrokerRequest struct {
+       HostAddress string `protobuf:"bytes,1,opt,name=hostAddress" 
json:"hostAddress,omitempty"`
+       Scheme      string `protobuf:"bytes,2,opt,name=scheme" 
json:"scheme,omitempty"`
+}
+
+func (m *BaseBrokerRequest) Reset()                    { *m = 
BaseBrokerRequest{} }
+func (m *BaseBrokerRequest) String() string            { return 
proto.CompactTextString(m) }
+func (*BaseBrokerRequest) ProtoMessage()               {}
+func (*BaseBrokerRequest) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{22} }
+
+func (m *BaseBrokerRequest) GetHostAddress() string {
+       if m != nil {
+               return m.HostAddress
+       }
+       return ""
+}
+
+func (m *BaseBrokerRequest) GetScheme() string {
+       if m != nil {
+               return m.Scheme
+       }
+       return ""
+}
+
+type BrokerAPIInfoEntry struct {
+       Href      string `protobuf:"bytes,1,opt,name=href" 
json:"href,omitempty"`
+       Name      string `protobuf:"bytes,2,opt,name=name" 
json:"name,omitempty"`
+       Title     string `protobuf:"bytes,3,opt,name=title" 
json:"title,omitempty"`
+       Templated bool   `protobuf:"varint,4,opt,name=templated" 
json:"templated,omitempty"`
+}
+
+func (m *BrokerAPIInfoEntry) Reset()                    { *m = 
BrokerAPIInfoEntry{} }
+func (m *BrokerAPIInfoEntry) String() string            { return 
proto.CompactTextString(m) }
+func (*BrokerAPIInfoEntry) ProtoMessage()               {}
+func (*BrokerAPIInfoEntry) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{23} }
+
+func (m *BrokerAPIInfoEntry) GetHref() string {
+       if m != nil {
+               return m.Href
+       }
+       return ""
+}
+
+func (m *BrokerAPIInfoEntry) GetName() string {
+       if m != nil {
+               return m.Name
+       }
+       return ""
+}
+
+func (m *BrokerAPIInfoEntry) GetTitle() string {
+       if m != nil {
+               return m.Title
+       }
+       return ""
+}
+
+func (m *BrokerAPIInfoEntry) GetTemplated() bool {
+       if m != nil {
+               return m.Templated
+       }
+       return false
+}
+
+type BrokerHomeResponse struct {
+       Response *services.Response             
`protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
+       XLinks   map[string]*BrokerAPIInfoEntry 
`protobuf:"bytes,2,rep,name=_links,json=Links" json:"_links,omitempty" 
protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+       Curies   []*BrokerAPIInfoEntry          
`protobuf:"bytes,3,rep,name=curies" json:"curies,omitempty"`
+}
+
+func (m *BrokerHomeResponse) Reset()                    { *m = 
BrokerHomeResponse{} }
+func (m *BrokerHomeResponse) String() string            { return 
proto.CompactTextString(m) }
+func (*BrokerHomeResponse) ProtoMessage()               {}
+func (*BrokerHomeResponse) Descriptor() ([]byte, []int) { return 
fileDescriptor0, []int{24} }
+
+func (m *BrokerHomeResponse) GetResponse() *services.Response {
+       if m != nil {
+               return m.Response
+       }
+       return nil
+}
+
+func (m *BrokerHomeResponse) GetXLinks() map[string]*BrokerAPIInfoEntry {
+       if m != nil {
+               return m.XLinks
+       }
+       return nil
+}
+
+func (m *BrokerHomeResponse) GetCuries() []*BrokerAPIInfoEntry {
+       if m != nil {
+               return m.Curies
+       }
+       return nil
+}
+
+func init() {
+       proto.RegisterType((*Participant)(nil), "Participant")
+       proto.RegisterType((*Version)(nil), "Version")
+       proto.RegisterType((*Pact)(nil), "Pact")
+       proto.RegisterType((*PactVersion)(nil), "PactVersion")
+       proto.RegisterType((*Tag)(nil), "Tag")
+       proto.RegisterType((*PublishPactRequest)(nil), "PublishPactRequest")
+       proto.RegisterType((*PublishPactResponse)(nil), "PublishPactResponse")
+       proto.RegisterType((*GetAllProviderPactsRequest)(nil), 
"GetAllProviderPactsRequest")
+       proto.RegisterType((*ConsumerInfo)(nil), "ConsumerInfo")
+       proto.RegisterType((*Links)(nil), "Links")
+       proto.RegisterType((*GetAllProviderPactsResponse)(nil), 
"GetAllProviderPactsResponse")
+       proto.RegisterType((*GetProviderConsumerVersionPactRequest)(nil), 
"GetProviderConsumerVersionPactRequest")
+       proto.RegisterType((*GetProviderConsumerVersionPactResponse)(nil), 
"GetProviderConsumerVersionPactResponse")
+       proto.RegisterType((*Verification)(nil), "Verification")
+       proto.RegisterType((*VerificationSummary)(nil), "VerificationSummary")
+       proto.RegisterType((*VerificationDetail)(nil), "VerificationDetail")
+       proto.RegisterType((*VerificationDetails)(nil), "VerificationDetails")
+       proto.RegisterType((*VerificationResult)(nil), "VerificationResult")
+       proto.RegisterType((*PublishVerificationRequest)(nil), 
"PublishVerificationRequest")
+       proto.RegisterType((*PublishVerificationResponse)(nil), 
"PublishVerificationResponse")
+       proto.RegisterType((*RetrieveVerificationRequest)(nil), 
"RetrieveVerificationRequest")
+       proto.RegisterType((*RetrieveVerificationResponse)(nil), 
"RetrieveVerificationResponse")
+       proto.RegisterType((*BaseBrokerRequest)(nil), "BaseBrokerRequest")
+       proto.RegisterType((*BrokerAPIInfoEntry)(nil), "BrokerAPIInfoEntry")
+       proto.RegisterType((*BrokerHomeResponse)(nil), "BrokerHomeResponse")
+}
+
+func init() { proto.RegisterFile("server/broker/broker.proto", 
fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+       // 1037 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 
0xdd, 0x8e, 0x1b, 0x35,
+       0x14, 0xd6, 0x64, 0x93, 0x6c, 0x72, 0x92, 0xd2, 0xe2, 0x2d, 0x28, 0x4a, 
0x4b, 0x15, 0x19, 0x8a,
+       0x02, 0x54, 0x59, 0xb1, 0xfc, 0x14, 0x21, 0x54, 0x69, 0x97, 0xae, 0xca, 
0x4a, 0xb4, 0x8a, 0x0c,
+       0xed, 0x05, 0x42, 0xaa, 0x26, 0x33, 0x27, 0x9b, 0x61, 0xe7, 0x0f, 0xdb, 
0x13, 0xb4, 0x17, 0xdc,
+       0x70, 0xc7, 0x63, 0xf0, 0x02, 0xf0, 0x06, 0x3c, 0x02, 0xcf, 0xc1, 0x15, 
0xcf, 0x80, 0xec, 0xb1,
+       0x27, 0x33, 0xc9, 0x64, 0xb7, 0x91, 0x10, 0x57, 0xf1, 0xf9, 0xf1, 0xf1, 
0x77, 0xbe, 0x73, 0xe6,
+       0xd8, 0x81, 0xa1, 0x40, 0xbe, 0x44, 0x7e, 0x38, 0xe3, 0xc9, 0x45, 0xf1, 
0x33, 0x49, 0x79, 0x22,
+       0x93, 0xe1, 0xc8, 0xd8, 0xbc, 0x84, 0xe3, 0xa1, 0x56, 0x1d, 0x2a, 0x4d, 
0xe0, 0xa1, 0xc8, 0x3d,
+       0xe8, 0x73, 0xe8, 0x4d, 0x5d, 0x2e, 0x03, 0x2f, 0x48, 0xdd, 0x58, 0x92, 
0xd7, 0xa0, 0x11, 0xf8,
+       0x03, 0x67, 0xe4, 0x8c, 0x5b, 0xac, 0x11, 0xf8, 0xe4, 0x36, 0xb4, 0xdc, 
0x34, 0x3d, 0xf3, 0x07,
+       0x8d, 0x91, 0x33, 0xee, 0xb2, 0x5c, 0x20, 0x23, 0xe8, 0x99, 0x30, 0xcf, 
0xdc, 0x08, 0x07, 0x7b,
+       0xda, 0x56, 0x56, 0xd1, 0x08, 0xf6, 0x5f, 0x20, 0x17, 0x41, 0x12, 0x6f, 
0x84, 0x7c, 0x13, 0xda,
+       0x71, 0x16, 0xcd, 0x90, 0x9b, 0x98, 0x46, 0x22, 0xef, 0xc0, 0x8d, 0x74, 
0x85, 0xe4, 0xcc, 0xd7,
+       0x61, 0x5b, 0xac, 0xaa, 0x54, 0x80, 0x12, 0xee, 0x23, 0x1f, 0x34, 0xb5, 
0x35, 0x17, 0xe8, 0xef,
+       0x0e, 0x34, 0xa7, 0xae, 0xb7, 0x89, 0xff, 0x63, 0x78, 0xc3, 0x4b, 0x62, 
0x91, 0x45, 0xc8, 0xa7,
+       0x95, 0xe0, 0x0d, 0xed, 0x52, 0x6f, 0x54, 0xbb, 0x52, 0x9e, 0x2c, 0x03, 
0x7f, 0x7d, 0x57, 0x0e,
+       0xa9, 0xde, 0x48, 0x6e, 0xc1, 0x9e, 0x58, 0xb8, 0x1a, 0x58, 0x9f, 0xa9, 
0x25, 0x19, 0xc0, 0xbe,
+       0x97, 0xc4, 0x12, 0x63, 0x39, 0x68, 0x69, 0xad, 0x15, 0xe9, 0xaf, 0x8e, 
0xe2, 0xdd, 0x93, 0xdb,
+       0x48, 0xba, 0x0b, 0xdd, 0x65, 0x6e, 0x2a, 0xb0, 0xae, 0x14, 0x8a, 0xc2, 
0xd4, 0xf5, 0x56, 0x80,
+       0x8c, 0xb4, 0x1d, 0x77, 0xf3, 0x0a, 0xdc, 0xf4, 0x21, 0xec, 0x7d, 0xeb, 
0x9e, 0x13, 0x02, 0xcd,
+       0x58, 0x55, 0xd3, 0xd1, 0x55, 0xd1, 0xeb, 0xab, 0x61, 0xd0, 0x5f, 0x1c, 
0x20, 0xd3, 0x6c, 0x16,
+       0x06, 0x62, 0xa1, 0x72, 0x61, 0xf8, 0x63, 0x86, 0x42, 0x92, 0x7b, 0x00, 
0xf6, 0xa0, 0x33, 0xdf,
+       0x84, 0x2b, 0x69, 0x94, 0xdd, 0xd2, 0x5e, 0x34, 0x56, 0x49, 0xa3, 0x58, 
0x33, 0x67, 0x98, 0xce,
+       0xb2, 0xa2, 0x82, 0xa8, 0x32, 0x35, 0x14, 0xeb, 0x35, 0xfd, 0x02, 0x0e, 
0x2a, 0x18, 0x44, 0x9a,
+       0xc4, 0x02, 0xc9, 0x7d, 0xe8, 0x70, 0xb3, 0xd6, 0x10, 0x7a, 0x47, 0xdd, 
0x89, 0x35, 0xb2, 0xc2,
+       0x44, 0x7f, 0x80, 0xe1, 0x13, 0x94, 0xc7, 0x61, 0x38, 0x2d, 0xa8, 0xf1, 
0xa4, 0x78, 0xd5, 0x4c,
+       0x1e, 0xc0, 0xfe, 0xcc, 0x15, 0xf8, 0x9c, 0x87, 0x3a, 0x8d, 0xde, 0x11, 
0x99, 0x9c, 0xb8, 0x02,
+       0x4f, 0xf4, 0x27, 0x68, 0x82, 0x30, 0xeb, 0x42, 0x3f, 0x85, 0xfe, 0x97, 
0x36, 0xcb, 0x78, 0x9e,
+       0xa8, 0x6c, 0x16, 0x1c, 0xe7, 0x96, 0x70, 0xb5, 0x2e, 0x8a, 0xd0, 0x58, 
0x15, 0x81, 0x3e, 0x80,
+       0xd6, 0xd7, 0x41, 0x7c, 0x21, 0xc8, 0xdb, 0xd0, 0x52, 0x29, 0x8b, 0x81, 
0x33, 0xda, 0x1b, 0xf7,
+       0x8e, 0x6e, 0x4c, 0xca, 0xe1, 0x58, 0x6e, 0xa3, 0x1e, 0xdc, 0xa9, 0xcd, 
0x68, 0x27, 0x5e, 0xc8,
+       0x5b, 0xd0, 0x7e, 0x19, 0xaa, 0x43, 0x4d, 0x62, 0xed, 0x89, 0x86, 0xc0, 
0x72, 0x24, 0xf4, 0x0f,
+       0x07, 0xee, 0x3f, 0x41, 0x69, 0x8f, 0xb0, 0x38, 0x4c, 0x37, 0xff, 0x3f, 
0xcd, 0x50, 0x22, 0xbf,
+       0x79, 0x3d, 0xf9, 0x1e, 0xbc, 0x7b, 0x1d, 0xe0, 0xdd, 0x18, 0xb2, 0xbd, 
0xd8, 0x28, 0xf5, 0xe2,
+       0xdf, 0x0e, 0xf4, 0x5f, 0x20, 0x0f, 0xe6, 0x81, 0xe7, 0xca, 0xeb, 0x67, 
0x5f, 0xab, 0x3a, 0xfb,
+       0x8a, 0x69, 0x50, 0x9e, 0x7d, 0x25, 0xa5, 0xe2, 0x42, 0x64, 0x9e, 0x87, 
0x42, 0xe8, 0x8c, 0x3b,
+       0xcc, 0x8a, 0x64, 0x0c, 0x37, 0x2d, 0xa7, 0xc6, 0x5d, 0x0f, 0x9c, 0x2e, 
0x5b, 0x57, 0x93, 0x21,
+       0x74, 0x66, 0x59, 0x10, 0xfa, 0x8a, 0xb6, 0xb6, 0x76, 0x29, 0x64, 0xf2, 
0x3e, 0xdc, 0x5a, 0x96,
+       0xd0, 0x3f, 0x76, 0x25, 0x0e, 0xf6, 0xb5, 0xcf, 0x86, 0x9e, 0x9e, 0xc3, 
0x41, 0x39, 0xd3, 0x6f,
+       0xb2, 0x28, 0x72, 0xf9, 0xa5, 0x2a, 0xa7, 0xc1, 0x34, 0xcf, 0x42, 0xdd, 
0xa7, 0x5d, 0x56, 0xd2,
+       0x28, 0x02, 0xe6, 0x6e, 0x10, 0xa2, 0x2a, 0xb5, 0xb2, 0x19, 0x49, 0xa5, 
0x96, 0xc5, 0x17, 0x71,
+       0xf2, 0x93, 0x2a, 0xb3, 0x32, 0x58, 0x91, 0xfe, 0xe9, 0x00, 0x29, 0x9f, 
0xf4, 0x18, 0xa5, 0x1b,
+       0x84, 0x84, 0x42, 0xdf, 0xa6, 0xf6, 0x6c, 0x35, 0xb5, 0x2a, 0x3a, 0xf2, 
0x08, 0x86, 0x56, 0x3e,
+       0x4e, 0xd3, 0xd0, 0x04, 0xb0, 0x04, 0xe5, 0xbd, 0x76, 0x85, 0x47, 0x99, 
0xef, 0xbd, 0x2a, 0xdf,
+       0x75, 0x4c, 0x35, 0xb7, 0x30, 0xf5, 0x7d, 0x95, 0xa9, 0x1c, 0xbf, 0x20, 
0xa7, 0x70, 0x50, 0x76,
+       0x65, 0x28, 0xb2, 0xb0, 0xf8, 0xb4, 0x0f, 0x26, 0x9b, 0x5b, 0x58, 0x9d, 
0x3f, 0xfd, 0x6d, 0x8d,
+       0x9e, 0x5c, 0x5f, 0x86, 0xee, 0x54, 0xa1, 0x3f, 0x5a, 0xb5, 0x8a, 0x29, 
0x9a, 0xf9, 0xc4, 0x6f,
+       0x4f, 0x6a, 0x0a, 0xca, 0xd6, 0x9d, 0xc9, 0x87, 0xd0, 0x7d, 0x89, 0xd1, 
0x0c, 0x7d, 0x1f, 0xf3,
+       0x36, 0x5d, 0xdf, 0x69, 0x12, 0x64, 0x9d, 0x53, 0xe3, 0x45, 0xff, 0x72, 
0x60, 0x68, 0x66, 0x74,
+       0x15, 0xea, 0x7f, 0x33, 0x22, 0xb6, 0xdd, 0x86, 0xdb, 0x3f, 0x97, 0xab, 
0x1b, 0xa3, 0x75, 0x5d,
+       0x63, 0xd0, 0x9f, 0xe1, 0x4e, 0x6d, 0x3e, 0xbb, 0x4d, 0x90, 0x87, 0xd0, 
0xf7, 0x92, 0x78, 0x1e,
+       0xf0, 0x48, 0x6f, 0x37, 0x65, 0xa8, 0x2d, 0x7d, 0xc5, 0x91, 0x9e, 0xc3, 
0x1d, 0x86, 0x92, 0x07,
+       0xb8, 0xc4, 0x2d, 0x7c, 0x96, 0xf8, 0x72, 0x36, 0xf8, 0x1a, 0xc3, 0x4d, 
0xaf, 0x3a, 0xff, 0x0c,
+       0xa9, 0xeb, 0x6a, 0xca, 0xe1, 0x6e, 0xfd, 0x41, 0xbb, 0x25, 0xfa, 0x01, 
0xb4, 0xb9, 0x6e, 0xcb,
+       0xda, 0x14, 0xf3, 0x8e, 0x65, 0xc6, 0x85, 0x3e, 0x85, 0xd7, 0x37, 0xc6, 
0xb8, 0x7a, 0x70, 0x2e,
+       0x12, 0x21, 0x8f, 0x7d, 0x9f, 0xdb, 0x96, 0xee, 0xb2, 0xb2, 0x4a, 0x35, 
0x81, 0xf0, 0x16, 0x58,
+       0x5c, 0x9d, 0x46, 0xa2, 0x29, 0x90, 0x3c, 0xd4, 0xf1, 0xf4, 0x4c, 0x5d, 
0x93, 0xa7, 0xb1, 0xe4,
+       0x97, 0xaf, 0x7a, 0xf5, 0xaa, 0xd7, 0xa6, 0x0c, 0x64, 0x68, 0x9f, 0xb8, 
0xb9, 0xa0, 0x5e, 0x45,
+       0x12, 0xa3, 0x34, 0x74, 0x25, 0xfa, 0xa6, 0xb5, 0x56, 0x0a, 0xfa, 0x8f, 
0x63, 0x8f, 0xfc, 0x2a,
+       0x89, 0x70, 0x57, 0xae, 0x3e, 0x29, 0x5d, 0xbc, 0x6a, 0x12, 0xdc, 0x9b, 
0x6c, 0xc6, 0xca, 0xef,
+       0x62, 0x9d, 0x89, 0xb9, 0x90, 0x15, 0xc5, 0x5e, 0xc6, 0x03, 0x14, 0x7a, 
0x7c, 0x2a, 0x8a, 0x37,
+       0xb3, 0x66, 0xc6, 0x65, 0xf8, 0x14, 0x60, 0x15, 0x41, 0x3d, 0x5b, 0x2f, 
0xf0, 0xd2, 0x50, 0xa1,
+       0x96, 0xe4, 0x3d, 0x68, 0x2d, 0xdd, 0x30, 0xc3, 0xa2, 0x5c, 0x35, 0xb1, 
0x72, 0x8f, 0xcf, 0x1b,
+       0x9f, 0x39, 0x27, 0x9d, 0xef, 0xda, 0xf9, 0x9f, 0x8e, 0x59, 0x5b, 0xff, 
0xa7, 0xf8, 0xe8, 0xdf,
+       0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0x8f, 0x7b, 0x26, 0x93, 0x0c, 0x00, 
0x00,
+}
diff --git a/server/broker/broker.proto b/server/broker/broker.proto
new file mode 100644
index 0000000..645e064
--- /dev/null
+++ b/server/broker/broker.proto
@@ -0,0 +1,158 @@
+syntax = "proto3";
+
+import "server/core/proto/services.proto";
+option go_package = "broker";
+
+/*
+Definitions of objects
+*/
+
+message Participant {
+       int32 id = 1;
+       string appId = 2;
+       string serviceName = 3;
+}
+
+message Version {
+       int32 id = 1;
+       string number = 2;
+       int32 participantId = 3;
+       int32 order = 4;
+}
+
+message Pact {
+       int32 id = 1;
+       int32 consumerParticipantId = 2;
+       int32 providerParticipantId = 3;
+       bytes sha = 4;
+       bytes content = 5;
+}
+
+message PactVersion {
+       int32 id = 1;
+       int32 versionId = 2;
+       int32 pactId = 3;
+       int32 providerParticipantId = 4;
+}
+
+message Tag {
+       string name = 1;
+       int32 versionId = 2;
+}
+
+message PublishPactRequest {
+    string providerId = 1;
+    string consumerId = 2;
+    string version = 3;
+    bytes pact = 4;
+}
+
+message PublishPactResponse {
+    Response response = 1;
+}
+
+message GetAllProviderPactsRequest {
+       string providerId = 1;
+  BaseBrokerRequest baseUrl = 2;
+}
+
+message ConsumerInfo {
+       string href = 1;
+       string name = 2;
+}
+
+message Links {
+       repeated ConsumerInfo pacts = 1;
+}
+
+message GetAllProviderPactsResponse {
+       Response response = 1;
+       Links _links = 2;
+}
+
+message GetProviderConsumerVersionPactRequest {
+       string providerId = 1;
+       string consumerId = 2;
+       string version = 3;
+  BaseBrokerRequest baseUrl = 4;
+}
+
+message GetProviderConsumerVersionPactResponse {
+       Response response = 1;
+       bytes pact = 2;
+}
+
+message Verification {
+       int32 id = 1;
+       int32 number = 2;
+       int32 pactVersionId = 3; // id of the version object
+       bool success = 4;
+       string providerVersion = 5;
+       string buildUrl = 6;
+       string verificationDate = 7;
+}
+
+message VerificationSummary {
+       repeated string successful = 1;
+       repeated string failed = 2;
+       repeated string unknown = 3;
+}
+
+message VerificationDetail {
+       string providerName = 1;
+       string providerApplicationVersion = 2;
+       bool success = 3;
+       string verificationDate = 4;
+}
+
+message VerificationDetails {
+       repeated VerificationDetail verificationResults = 1;
+}
+
+message VerificationResult {
+       bool success = 1;
+       VerificationSummary providerSummary = 2;
+       VerificationDetails _embedded = 3;
+}
+
+message PublishVerificationRequest {
+       string providerId = 1;
+       string consumerId = 2;
+       int32 pactId = 3;
+       bool success = 4;
+       string providerApplicationVersion = 5;
+}
+
+message PublishVerificationResponse {
+       Response response = 1;
+       VerificationDetail confirmation = 2;
+}
+
+message RetrieveVerificationRequest {
+       string consumerId = 1;
+       string consumerVersion = 2;
+}
+
+message RetrieveVerificationResponse {
+       Response response = 1;
+       VerificationResult result = 2;
+}
+
+message BaseBrokerRequest {
+       string hostAddress = 1;
+       string scheme = 2;
+}
+
+
+message BrokerAPIInfoEntry {
+       string href = 1;
+       string name = 2;
+       string title = 3;
+       bool templated = 4;
+}
+
+message BrokerHomeResponse {
+       Response response = 1;
+       map<string, BrokerAPIInfoEntry> _links = 2;
+       repeated BrokerAPIInfoEntry curies = 3;
+}
diff --git a/server/broker/broker_key_generator.go 
b/server/broker/broker_key_generator.go
new file mode 100644
index 0000000..e10ebdb
--- /dev/null
+++ b/server/broker/broker_key_generator.go
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "strconv"
+
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
+)
+
+const (
+       BROKER_ROOT_KEY              = "cse-pact"
+       BROKER_PARTICIPANT_KEY       = "participant"
+       BROKER_VERSION_KEY           = "version"
+       BROKER_PACT_KEY              = "pact"
+       BROKER_PACT_VERSION_KEY      = "pact-version"
+       BROKER_PACT_TAG_KEY          = "pact-tag"
+       BROKER_PACT_VERIFICATION_KEY = "verification"
+       BROKER_PACT_LATEST           = "latest"
+)
+
+// GetBrokerRootKey returns url (/cse-pact)
+func GetBrokerRootKey() string {
+       return util.StringJoin([]string{
+               "",
+               BROKER_ROOT_KEY,
+       }, "/")
+}
+
+//GetBrokerLatestKey returns  pact related keys
+func GetBrokerLatestKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PACT_LATEST,
+               tenant,
+       }, "/")
+}
+
+//GetBrokerParticipantKey returns the participant root key
+func GetBrokerParticipantKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PARTICIPANT_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerParticipantKey returns the participant key
+func GenerateBrokerParticipantKey(tenant string, appId string, serviceName 
string) string {
+       return util.StringJoin([]string{
+               GetBrokerParticipantKey(tenant),
+               appId,
+               serviceName,
+       }, "/")
+}
+
+//GetBrokerVersionKey returns th root version key
+func GetBrokerVersionKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_VERSION_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerVersionKey returns the version key
+func GenerateBrokerVersionKey(tenant string, number string, participantId 
int32) string {
+       return util.StringJoin([]string{
+               GetBrokerVersionKey(tenant),
+               number,
+               strconv.Itoa(int(participantId)),
+       }, "/")
+}
+
+//GetBrokerPactKey returns the pact root key
+func GetBrokerPactKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PACT_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerPactKey returns the pact key
+func GenerateBrokerPactKey(tenant string, consumerParticipantId int32,
+       providerParticipantId int32, sha []byte) string {
+       return util.StringJoin([]string{
+               GetBrokerPactKey(tenant),
+               strconv.Itoa(int(consumerParticipantId)),
+               strconv.Itoa(int(providerParticipantId)),
+               string(sha),
+       }, "/")
+}
+
+//GetBrokerPactVersionKey returns the pact version root key
+func GetBrokerPactVersionKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PACT_VERSION_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerPactVersionKey returns the pact version root key
+func GenerateBrokerPactVersionKey(tenant string, versionId int32, pactId 
int32) string {
+       return util.StringJoin([]string{
+               GetBrokerPactVersionKey(tenant),
+               strconv.Itoa(int(versionId)),
+               strconv.Itoa(int(pactId)),
+       }, "/")
+}
+
+//GetBrokerTagKey returns the broker tag root key
+func GetBrokerTagKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PACT_TAG_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerTagKey returns the broker tag key
+func GenerateBrokerTagKey(tenant string, versionId int32) string {
+       return util.StringJoin([]string{
+               GetBrokerTagKey(tenant),
+               strconv.Itoa(int(versionId)),
+       }, "/")
+}
+
+//GetBrokerVerificationKey returns the verification root key
+func GetBrokerVerificationKey(tenant string) string {
+       return util.StringJoin([]string{
+               GetBrokerRootKey(),
+               BROKER_PACT_VERIFICATION_KEY,
+               tenant,
+       }, "/")
+}
+
+//GenerateBrokerVerificationKey returns he verification key
+func GenerateBrokerVerificationKey(tenant string, pactVersionId int32, number 
int32) string {
+       return util.StringJoin([]string{
+               GetBrokerVerificationKey(tenant),
+               strconv.Itoa(int(pactVersionId)),
+               strconv.Itoa(int(number)),
+       }, "/")
+}
+
+//GetBrokerLatestParticipantIDKey returns the latest participant ID
+func GetBrokerLatestParticipantIDKey() string {
+       return util.StringJoin([]string{
+               GetBrokerLatestKey("default"),
+               BROKER_PARTICIPANT_KEY,
+       }, "/")
+}
+
+//GetBrokerLatestVersionIDKey returns latest version ID
+func GetBrokerLatestVersionIDKey() string {
+       return util.StringJoin([]string{
+               GetBrokerLatestKey("default"),
+               BROKER_VERSION_KEY,
+       }, "/")
+}
+
+//GetBrokerLatestPactIDKey returns latest pact ID
+func GetBrokerLatestPactIDKey() string {
+       return util.StringJoin([]string{
+               GetBrokerLatestKey("default"),
+               BROKER_PACT_KEY,
+       }, "/")
+}
+
+//GetBrokerLatestPactVersionIDKey returns lated pact version ID
+func GetBrokerLatestPactVersionIDKey() string {
+       return util.StringJoin([]string{
+               GetBrokerLatestKey("default"),
+               BROKER_PACT_VERSION_KEY,
+       }, "/")
+}
+
+//GetBrokerLatestVerificationIDKey returns the lastest verification ID
+func GetBrokerLatestVerificationIDKey() string {
+       return util.StringJoin([]string{
+               GetBrokerLatestKey("default"),
+               BROKER_PACT_VERIFICATION_KEY,
+       }, "/")
+}
diff --git a/server/broker/controller.go b/server/broker/controller.go
new file mode 100644
index 0000000..2f817c5
--- /dev/null
+++ b/server/broker/controller.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "encoding/json"
+       "io/ioutil"
+       "net/http"
+       "strconv"
+
+       "github.com/apache/incubator-servicecomb-service-center/pkg/rest"
+       scerr 
"github.com/apache/incubator-servicecomb-service-center/server/error"
+       
"github.com/apache/incubator-servicecomb-service-center/server/rest/controller"
+)
+
+const DEFAULT_SCHEME = "http"
+
+type BrokerController struct {
+}
+
+func (brokerService *BrokerController) URLPatterns() []rest.Route {
+       return []rest.Route{
+               // for handling broker requests
+               {rest.HTTP_METHOD_GET,
+                       "/",
+                       brokerService.GetHome},
+               {rest.HTTP_METHOD_PUT,
+                       
"/pacts/provider/:providerId/consumer/:consumerId/version/:number",
+                       brokerService.PublishPact},
+               {rest.HTTP_METHOD_GET,
+                       "/pacts/provider/:providerId/latest",
+                       brokerService.GetAllProviderPacts},
+               {rest.HTTP_METHOD_GET,
+                       
"/pacts/provider/:providerId/consumer/:consumerId/version/:number",
+                       brokerService.GetPactsOfProvider},
+               {rest.HTTP_METHOD_DELETE,
+                       "/pacts/delete",
+                       brokerService.DeletePacts},
+               {rest.HTTP_METHOD_POST,
+                       
"/pacts/provider/:providerId/consumer/:consumerId/pact-version/:sha/verification-results",
+                       brokerService.PublishVerificationResults},
+               {rest.HTTP_METHOD_GET,
+                       
"/verification-results/consumer/:consumerId/version/:consumerVersion/latest",
+                       brokerService.RetrieveVerificationResults},
+       }
+}
+
+func (brokerService *BrokerController) GetHome(w http.ResponseWriter, r 
*http.Request) {
+       request := &BaseBrokerRequest{
+               HostAddress: r.Host,
+               Scheme:      getScheme(r),
+       }
+       resp, _ := BrokerServiceAPI.GetBrokerHome(r.Context(), request)
+
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func (*BrokerController) PublishPact(w http.ResponseWriter, r *http.Request) {
+       message, err := ioutil.ReadAll(r.Body)
+       if err != nil {
+               PactLogger.Error("body err\n", err)
+               controller.WriteError(w, scerr.ErrInvalidParams, err.Error())
+               return
+       }
+       request := &PublishPactRequest{
+               ProviderId: r.URL.Query().Get(":providerId"),
+               ConsumerId: r.URL.Query().Get(":consumerId"),
+               Version:    r.URL.Query().Get(":number"),
+               Pact:       message,
+       }
+       PactLogger.Infof("PublishPact: providerId = %s, consumerId = %s, 
version = %s\n",
+               request.ProviderId, request.ConsumerId, request.Version)
+       resp, err := BrokerServiceAPI.PublishPact(r.Context(), request)
+
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func (*BrokerController) GetAllProviderPacts(w http.ResponseWriter, r 
*http.Request) {
+       request := &GetAllProviderPactsRequest{
+               ProviderId: r.URL.Query().Get(":providerId"),
+               BaseUrl: &BaseBrokerRequest{
+                       HostAddress: r.Host,
+                       Scheme:      getScheme(r),
+               },
+       }
+       resp, err := BrokerServiceAPI.GetAllProviderPacts(r.Context(), request 
/*, href*/)
+       linksObj, err := json.Marshal(resp)
+       if err != nil {
+               return
+       }
+       PactLogger.Infof("Pact info: %s\n", string(linksObj))
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func (*BrokerController) GetPactsOfProvider(w http.ResponseWriter, r 
*http.Request) {
+       request := &GetProviderConsumerVersionPactRequest{
+               ProviderId: r.URL.Query().Get(":providerId"),
+               ConsumerId: r.URL.Query().Get(":consumerId"),
+               Version:    r.URL.Query().Get(":number"),
+               BaseUrl: &BaseBrokerRequest{
+                       HostAddress: r.Host,
+                       Scheme:      getScheme(r),
+               },
+       }
+
+       resp, _ := BrokerServiceAPI.GetPactsOfProvider(r.Context(), request)
+       respInternal := resp.Response
+       resp.Response = nil
+       //controller.WriteResponse(w, respInternal, resp.Pact)
+       controller.WriteBytes(w, respInternal, resp.Pact)
+}
+
+func (*BrokerController) DeletePacts(w http.ResponseWriter, r *http.Request) {
+       resp, _ := BrokerServiceAPI.DeletePacts(r.Context(), &BaseBrokerRequest{
+               HostAddress: r.Host,
+               Scheme:      getScheme(r),
+       })
+       controller.WriteResponse(w, resp, nil)
+}
+
+func (*BrokerController) PublishVerificationResults(w http.ResponseWriter, r 
*http.Request) {
+       requestBody, err := ioutil.ReadAll(r.Body)
+       if err != nil {
+               PactLogger.Error("body err", err)
+               controller.WriteError(w, scerr.ErrInvalidParams, err.Error())
+               return
+       }
+       request := &PublishVerificationRequest{}
+       err = json.Unmarshal(requestBody, request)
+       if err != nil {
+               PactLogger.Error("Unmarshal error", err)
+               controller.WriteError(w, scerr.ErrInvalidParams, err.Error())
+               return
+       }
+       request.ProviderId = r.URL.Query().Get(":providerId")
+       request.ConsumerId = r.URL.Query().Get(":consumerId")
+       i, err := strconv.ParseInt(r.URL.Query().Get(":sha"), 10, 32)
+       if err != nil {
+               PactLogger.Error("Invalid pactId", err)
+               controller.WriteError(w, scerr.ErrInvalidParams, err.Error())
+               return
+       }
+       request.PactId = int32(i)
+       PactLogger.Infof("PublishVerificationResults: %s, %s, %d, %t, %s\n",
+               request.ProviderId, request.ConsumerId, request.PactId, 
request.Success,
+               request.ProviderApplicationVersion)
+       resp, err := BrokerServiceAPI.PublishVerificationResults(r.Context(),
+               request)
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func (*BrokerController) RetrieveVerificationResults(w http.ResponseWriter, r 
*http.Request) {
+       request := &RetrieveVerificationRequest{}
+       request.ConsumerId = r.URL.Query().Get(":consumerId")
+       request.ConsumerVersion = r.URL.Query().Get(":consumerVersion")
+       PactLogger.Infof("Retrieve verification results for: %s, %s\n",
+               request.ConsumerId, request.ConsumerVersion)
+       resp, _ := BrokerServiceAPI.RetrieveVerificationResults(r.Context(), 
request)
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func getScheme(r *http.Request) string {
+       if len(r.URL.Scheme) < 1 {
+               return DEFAULT_SCHEME
+       }
+       return r.URL.Scheme
+}
diff --git a/server/broker/service.go b/server/broker/service.go
new file mode 100644
index 0000000..bde8f3e
--- /dev/null
+++ b/server/broker/service.go
@@ -0,0 +1,874 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "crypto/sha1"
+       "encoding/json"
+       "fmt"
+       "math"
+       "strconv"
+       "strings"
+       "time"
+
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
+       apt "github.com/apache/incubator-servicecomb-service-center/server/core"
+       pb 
"github.com/apache/incubator-servicecomb-service-center/server/core/proto"
+       scerr 
"github.com/apache/incubator-servicecomb-service-center/server/error"
+       
"github.com/apache/incubator-servicecomb-service-center/server/infra/registry"
+       serviceUtil 
"github.com/apache/incubator-servicecomb-service-center/server/service/util"
+       "golang.org/x/net/context"
+)
+
+var BrokerServiceAPI *BrokerService = &BrokerService{}
+
+type BrokerService struct {
+}
+
+func (*BrokerService) GetBrokerHome(ctx context.Context,
+       in *BaseBrokerRequest) (*BrokerHomeResponse, error) {
+
+       if in == nil || len(in.HostAddress) == 0 {
+               PactLogger.Errorf(nil, "Get Participant versions request 
failed: invalid params.")
+               return &BrokerHomeResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+
+       return GetBrokerHomeResponse(in.HostAddress, in.Scheme), nil
+}
+
+func (*BrokerService) GetPactsOfProvider(ctx context.Context,
+       in *GetProviderConsumerVersionPactRequest) 
(*GetProviderConsumerVersionPactResponse, error) {
+       PactLogger.Infof("GetPactsOfProvider: (%s, %s, %s)\n",
+               in.ProviderId, in.ConsumerId, in.Version)
+
+       resp, pactId, err := RetrieveProviderConsumerPact(ctx, in)
+       if err != nil || resp.GetPact() == nil || pactId == -1 {
+               PactLogger.Errorf(nil, "Get pacts of provider failed: %s\n",
+                       resp.Response.Message)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
err.Error()),
+               }, err
+       }
+
+       urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, 
in.BaseUrl.HostAddress,
+               BROKER_PUBLISH_VERIFICATION_URL,
+               strings.NewReplacer(":providerId", in.ProviderId,
+                       ":consumerId", in.ConsumerId,
+                       ":pact", fmt.Sprint(pactId)))
+
+       links := ",\"_links\": {" +
+               "\"pb:publish-verification-results\": {" +
+               "\"title\": \"Publish verification results\"," +
+               "\"href\": \"" + urlValue +
+               "\"" +
+               "}" +
+               "}}"
+
+       linksBytes := []byte(links)
+       pactBytes := resp.GetPact()
+       sliceOfResp := pactBytes[0 : len(pactBytes)-2]
+       finalBytes := append(sliceOfResp, linksBytes...)
+
+       return &GetProviderConsumerVersionPactResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "Success."),
+               Pact:     finalBytes,
+       }, nil
+       //controller.WriteText(http.StatusBadRequest, resp.Response.Message, w)
+
+}
+
+func (*BrokerService) DeletePacts(ctx context.Context,
+       in *BaseBrokerRequest) (*pb.Response, error) {
+
+       resp, err := DeletePactData(ctx, in)
+
+       return resp, err
+}
+
+func (*BrokerService) RetrieveProviderPacts(ctx context.Context,
+       in *GetAllProviderPactsRequest) (*GetAllProviderPactsResponse, error) {
+       if in == nil || len(in.ProviderId) == 0 {
+               PactLogger.Errorf(nil, "all provider pact retrieve request 
failed: invalid params.")
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+       tenant := GetDefaultTenantProject()
+
+       provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
+       if err != nil {
+               PactLogger.Errorf(err, "all provider pact retrieve failed, 
providerId is %s: query provider failed.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query provider failed."),
+               }, err
+       }
+       if provider == nil {
+               PactLogger.Errorf(nil, "all provider pact retrieve failed, 
providerId is %s: provider not exist.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider does not exist."),
+               }, nil
+       }
+       // Get the provider participant
+       //providerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, 
provider.AppId, provider.ServiceName)
+       providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, 
provider.ServiceName)
+       if err != nil || providerParticipant == nil {
+               PactLogger.Errorf(nil, "all provider pact retrieve failed, 
provider participant cannot be searched.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider participant cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("[RetrieveProviderPacts] Provider participant id : 
%d", providerParticipant.Id)
+       // Get all versions
+       versionKey := util.StringJoin([]string{GetBrokerVersionKey(tenant), 
""}, "/")
+       versions, err := Store().Version().Search(ctx,
+               registry.WithPrefix(),
+               registry.WithStrKey(versionKey))
+
+       if err != nil {
+               return nil, err
+       }
+       if len(versions.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPacts] No versions found, 
sorry")
+               return nil, nil
+       }
+       // Store versions in a map
+       versionObjects := make(map[int32]Version)
+       for i := 0; i < len(versions.Kvs); i++ {
+               version := &Version{}
+               err = json.Unmarshal(versions.Kvs[i].Value, version)
+               if err != nil {
+                       return nil, err
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Version found : (%d, 
%s)", version.Id, version.Number)
+               versionObjects[version.Id] = *version
+       }
+       // Get all pactversions and filter using the provider participant id
+       pactVersionKey := 
util.StringJoin([]string{GetBrokerPactVersionKey(tenant), ""}, "/")
+       pactVersions, err := Store().PactVersion().Search(ctx,
+               registry.WithStrKey(pactVersionKey),
+               registry.WithPrefix())
+
+       if err != nil {
+               return nil, err
+       }
+       if len(pactVersions.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPacts] No pact version found, 
sorry")
+               return nil, nil
+       }
+       participantToVersionObj := make(map[int32]Version)
+       for i := 0; i < len(pactVersions.Kvs); i++ {
+               pactVersion := &PactVersion{}
+               err = json.Unmarshal(pactVersions.Kvs[i].Value, pactVersion)
+               if err != nil {
+                       return nil, err
+               }
+               if pactVersion.ProviderParticipantId != providerParticipant.Id {
+                       continue
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Pact version found: 
(%d, %d, %d, %d)", pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, 
pactVersion.ProviderParticipantId)
+               vObj := versionObjects[pactVersion.VersionId]
+               if v1Obj, ok := participantToVersionObj[vObj.ParticipantId]; ok 
{
+                       if vObj.Order > v1Obj.Order {
+                               participantToVersionObj[vObj.ParticipantId] = 
vObj
+                       }
+               } else {
+                       participantToVersionObj[vObj.ParticipantId] = vObj
+               }
+       }
+       // Get all participants
+       participantKey := 
util.StringJoin([]string{GetBrokerParticipantKey(tenant), ""}, "/")
+       participants, err := Store().Participant().Search(ctx,
+               registry.WithStrKey(participantKey),
+               registry.WithPrefix())
+
+       if err != nil {
+               return nil, err
+       }
+       if len(participants.Kvs) == 0 {
+               return nil, nil
+       }
+       consumerInfoArr := make([]*ConsumerInfo, 0)
+       for i := 0; i < len(participants.Kvs); i++ {
+               participant := &Participant{}
+               err = json.Unmarshal(participants.Kvs[i].Value, participant)
+               if err != nil {
+                       return nil, err
+               }
+               if _, ok := participantToVersionObj[participant.Id]; !ok {
+                       continue
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Consumer found: (%d, 
%s, %s)", participant.Id, participant.AppId, participant.ServiceName)
+               consumerVersion := 
participantToVersionObj[participant.Id].Number
+               consumerId, err := serviceUtil.GetServiceId(ctx, 
&pb.MicroServiceKey{
+                       Tenant:      tenant,
+                       AppId:       participant.AppId,
+                       ServiceName: participant.ServiceName,
+                       Version:     consumerVersion,
+               })
+               if err != nil {
+                       return nil, err
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Consumer microservice 
found: %s", consumerId)
+
+               urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, 
in.BaseUrl.HostAddress,
+                       BROKER_PUBLISH_URL,
+                       strings.NewReplacer(":providerId", in.ProviderId,
+                               ":consumerId", consumerId,
+                               ":number", consumerVersion))
+
+               consumerInfo := &ConsumerInfo{
+                       Href: urlValue,
+                       Name: consumerId,
+               }
+               consumerInfoArr = append(consumerInfoArr, consumerInfo)
+       }
+       links := &Links{
+               Pacts: consumerInfoArr,
+       }
+       resJson, err := json.Marshal(links)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("Json : %s", string(resJson))
+       response := &GetAllProviderPactsResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "retrieve 
provider pact info succeeded."),
+               XLinks:   links,
+       }
+       return response, nil
+}
+
+func (*BrokerService) GetAllProviderPacts(ctx context.Context,
+       in *GetAllProviderPactsRequest) (*GetAllProviderPactsResponse, error) {
+
+       if in == nil || len(in.ProviderId) == 0 {
+               PactLogger.Errorf(nil, "all provider pact retrieve request 
failed: invalid params.")
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+       tenant := GetDefaultTenantProject()
+
+       provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
+       if err != nil {
+               PactLogger.Errorf(err, "all provider pact retrieve failed, 
providerId is %s: query provider failed.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query provider failed."),
+               }, err
+       }
+       if provider == nil {
+               PactLogger.Errorf(nil, "all provider pact retrieve failed, 
providerId is %s: provider not exist.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider does not exist."),
+               }, nil
+       }
+       // Get the provider participant
+       //providerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, 
provider.AppId, provider.ServiceName)
+       providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, 
provider.ServiceName)
+       if err != nil || providerParticipant == nil {
+               PactLogger.Errorf(nil, "all provider pact retrieve failed, 
provider participant cannot be searched.", in.ProviderId)
+               return &GetAllProviderPactsResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider participant cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("[RetrieveProviderPacts] Provider participant id : 
%d", providerParticipant.Id)
+       // Get all versions
+       versionKey := util.StringJoin([]string{GetBrokerVersionKey(tenant), 
""}, "/")
+       versions, err := Store().Version().Search(ctx,
+               registry.WithPrefix(),
+               registry.WithStrKey(versionKey))
+
+       if err != nil {
+               return nil, err
+       }
+       if len(versions.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPacts] No versions found, 
sorry")
+               return nil, nil
+       }
+       // Store versions in a map
+       versionObjects := make(map[int32]Version)
+       for i := 0; i < len(versions.Kvs); i++ {
+               version := &Version{}
+               err = json.Unmarshal(versions.Kvs[i].Value, version)
+               if err != nil {
+                       return nil, err
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Version found : (%d, 
%s)", version.Id, version.Number)
+               versionObjects[version.Id] = *version
+       }
+       // Get all pactversions and filter using the provider participant id
+       pactVersionKey := 
util.StringJoin([]string{GetBrokerPactVersionKey(tenant), ""}, "/")
+       pactVersions, err := Store().PactVersion().Search(ctx,
+               registry.WithStrKey(pactVersionKey),
+               registry.WithPrefix())
+
+       if err != nil {
+               return nil, err
+       }
+       if len(pactVersions.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPacts] No pact version found, 
sorry")
+               return nil, nil
+       }
+       participantToVersionObj := make(map[int32]Version)
+       for i := 0; i < len(pactVersions.Kvs); i++ {
+               pactVersion := &PactVersion{}
+               err = json.Unmarshal(pactVersions.Kvs[i].Value, pactVersion)
+               if err != nil {
+                       return nil, err
+               }
+               if pactVersion.ProviderParticipantId != providerParticipant.Id {
+                       continue
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Pact version found: 
(%d, %d, %d, %d)", pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, 
pactVersion.ProviderParticipantId)
+               vObj := versionObjects[pactVersion.VersionId]
+               if v1Obj, ok := participantToVersionObj[vObj.ParticipantId]; ok 
{
+                       if vObj.Order > v1Obj.Order {
+                               participantToVersionObj[vObj.ParticipantId] = 
vObj
+                       }
+               } else {
+                       participantToVersionObj[vObj.ParticipantId] = vObj
+               }
+       }
+       // Get all participants
+       participantKey := 
util.StringJoin([]string{GetBrokerParticipantKey(tenant), ""}, "/")
+       participants, err := Store().Participant().Search(ctx,
+               registry.WithStrKey(participantKey),
+               registry.WithPrefix())
+
+       if err != nil {
+               return nil, err
+       }
+       if len(participants.Kvs) == 0 {
+               return nil, nil
+       }
+       consumerInfoArr := make([]*ConsumerInfo, 0)
+       for i := 0; i < len(participants.Kvs); i++ {
+               participant := &Participant{}
+               err = json.Unmarshal(participants.Kvs[i].Value, participant)
+               if err != nil {
+                       return nil, err
+               }
+               if _, ok := participantToVersionObj[participant.Id]; !ok {
+                       continue
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Consumer found: (%d, 
%s, %s)", participant.Id, participant.AppId, participant.ServiceName)
+               consumerVersion := 
participantToVersionObj[participant.Id].Number
+               consumerId, err := serviceUtil.GetServiceId(ctx, 
&pb.MicroServiceKey{
+                       Tenant:      tenant,
+                       AppId:       participant.AppId,
+                       ServiceName: participant.ServiceName,
+                       Version:     consumerVersion,
+               })
+               if err != nil {
+                       return nil, err
+               }
+               PactLogger.Infof("[RetrieveProviderPacts] Consumer microservice 
found: %s", consumerId)
+
+               urlValue := GenerateBrokerAPIPath(in.BaseUrl.Scheme, 
in.BaseUrl.HostAddress,
+                       BROKER_PUBLISH_URL,
+                       strings.NewReplacer(":providerId", in.ProviderId,
+                               ":consumerId", consumerId,
+                               ":number", consumerVersion))
+
+               consumerInfo := &ConsumerInfo{
+                       Href: urlValue,
+                       Name: consumerId,
+               }
+               consumerInfoArr = append(consumerInfoArr, consumerInfo)
+       }
+       links := &Links{
+               Pacts: consumerInfoArr,
+       }
+       resJson, err := json.Marshal(links)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("Json : %s", string(resJson))
+       response := &GetAllProviderPactsResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "retrieve 
provider pact info succeeded."),
+               XLinks:   links,
+       }
+       return response, nil
+}
+
+func (*BrokerService) RetrieveVerificationResults(ctx context.Context, in 
*RetrieveVerificationRequest) (*RetrieveVerificationResponse, error) {
+       if in == nil || len(in.ConsumerId) == 0 || len(in.ConsumerVersion) == 0 
{
+               PactLogger.Errorf(nil, "verification result retrieve request 
failed: invalid params.")
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+       tenant := GetDefaultTenantProject()
+       consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
+       if err != nil {
+               PactLogger.Errorf(err, "verification result retrieve request 
failed, consumerId is %s: query consumer failed.", in.ConsumerId)
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query consumer failed."),
+               }, err
+       }
+       if consumer == nil {
+               PactLogger.Errorf(nil, "verification result retrieve request 
failed, consumerId is %s: consumer not exist.", in.ConsumerId)
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Consumer does not exist."),
+               }, nil
+       }
+       PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", 
consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
+       // Get consumer participant
+       consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, 
consumer.ServiceName)
+       if err != nil || consumerParticipant == nil {
+               PactLogger.Errorf(nil, "verification result retrieve request 
failed, consumer participant cannot be searched.", in.ConsumerId)
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"consumer participant cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("Consumer participant found: (%d, %s, %s)", 
consumerParticipant.Id, consumerParticipant.AppId, 
consumerParticipant.ServiceName)
+       // Get version
+       version, err := GetVersion(ctx, tenant, consumer.Version, 
consumerParticipant.Id)
+       if err != nil || version == nil {
+               PactLogger.Errorf(nil, "verification result retrieve request 
failed, version cannot be searched.")
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"version cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, 
version.Number, version.ParticipantId, version.Order)
+       key := util.StringJoin([]string{GetBrokerPactVersionKey(tenant), 
strconv.Itoa(int(version.Id))}, "/")
+       pactVersions, err := Store().PactVersion().Search(ctx,
+               registry.WithPrefix(),
+               registry.WithStrKey(key))
+
+       if err != nil || len(pactVersions.Kvs) == 0 {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, pact version cannot be searched.")
+               return &RetrieveVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact version cannot be searched."),
+               }, err
+       }
+       overAllSuccess := false
+
+       successfuls := make([]string, 0)
+       fails := make([]string, 0)
+       unknowns := make([]string, 0)
+
+       verificationDetailsArr := make([]*VerificationDetail, 0)
+       for j := 0; j < len(pactVersions.Kvs); j++ {
+               pactVersion := &PactVersion{}
+               err = json.Unmarshal(pactVersions.Kvs[j].Value, &pactVersion)
+               if err != nil {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, pact version cannot be searched.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "pact version cannot be searched."),
+                       }, err
+               }
+               key = 
util.StringJoin([]string{GetBrokerVerificationKey(tenant), 
strconv.Itoa(int(pactVersion.Id))}, "/")
+               verifications, err := Store().Verification().Search(ctx,
+                       registry.WithPrefix(),
+                       registry.WithStrKey(key))
+
+               if err != nil || len(verifications.Kvs) == 0 {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, verification results cannot be searched.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification results cannot be 
searched."),
+                       }, err
+               }
+               lastNumber := int32(math.MinInt32)
+               var lastVerificationResult *Verification
+               for i := 0; i < len(verifications.Kvs); i++ {
+                       verification := &Verification{}
+                       err = json.Unmarshal(verifications.Kvs[i].Value, 
&verification)
+                       if err != nil {
+                               PactLogger.Errorf(nil, "verification result 
retrieve request failed, verification result unmarshall error.")
+                               return &RetrieveVerificationResponse{
+                                       Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall 
error."),
+                               }, err
+                       }
+                       if verification.Number > lastNumber {
+                               lastNumber = verification.Number
+                               lastVerificationResult = verification
+                       }
+               }
+               if lastVerificationResult == nil {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, verification result cannot be found.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification result cannot be 
found."),
+                       }, err
+               }
+               PactLogger.Infof("Verification result found: (%d, %d, %d, %t, 
%s, %s, %s)",
+                       lastVerificationResult.Id, 
lastVerificationResult.Number, lastVerificationResult.PactVersionId,
+                       lastVerificationResult.Success, 
lastVerificationResult.ProviderVersion,
+                       lastVerificationResult.BuildUrl, 
lastVerificationResult.VerificationDate)
+
+               key = util.StringJoin([]string{GetBrokerParticipantKey(tenant), 
""}, "/")
+               participants, err := Store().Participant().Search(ctx,
+                       registry.WithStrKey(key),
+                       registry.WithPrefix())
+
+               if err != nil || len(participants.Kvs) == 0 {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, provider participant cannot be searched.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "provider participant cannot be 
searched."),
+                       }, err
+               }
+               var providerParticipant *Participant
+               for i := 0; i < len(participants.Kvs); i++ {
+                       participant := &Participant{}
+                       err = json.Unmarshal(participants.Kvs[i].Value, 
&participant)
+                       if err != nil {
+                               PactLogger.Errorf(nil, "verification result 
retrieve request failed, verification result unmarshall error.")
+                               return &RetrieveVerificationResponse{
+                                       Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall 
error."),
+                               }, err
+                       }
+                       if participant.Id == pactVersion.ProviderParticipantId {
+                               providerParticipant = participant
+                               break
+                       }
+               }
+               if providerParticipant == nil {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, verification result unmarshall error.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall 
error."),
+                       }, err
+               }
+               serviceFindReq := &pb.GetExistenceRequest{
+                       Type:        "microservice",
+                       AppId:       providerParticipant.AppId,
+                       ServiceName: providerParticipant.ServiceName,
+                       Version:     lastVerificationResult.ProviderVersion,
+               }
+               resp, err := apt.ServiceAPI.Exist(ctx, serviceFindReq)
+               if err != nil {
+                       PactLogger.Errorf(nil, "verification result retrieve 
request failed, provider service cannot be found.")
+                       return &RetrieveVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "provider service cannot be found."),
+                       }, err
+               }
+               providerName := resp.ServiceId
+               verificationDetail := &VerificationDetail{
+                       ProviderName:               providerName,
+                       ProviderApplicationVersion: 
lastVerificationResult.ProviderVersion,
+                       Success:                    
lastVerificationResult.Success,
+                       VerificationDate:           
lastVerificationResult.VerificationDate,
+               }
+               verificationDetailsArr = append(verificationDetailsArr, 
verificationDetail)
+               if verificationDetail.Success == true {
+                       successfuls = append(successfuls, providerName)
+               } else {
+                       fails = append(fails, providerName)
+               }
+               overAllSuccess = overAllSuccess && verificationDetail.Success
+       }
+       verificationDetails := &VerificationDetails{VerificationResults: 
verificationDetailsArr}
+       verificationSummary := &VerificationSummary{Successful: successfuls, 
Failed: fails, Unknown: unknowns}
+       verificationResult := &VerificationResult{Success: overAllSuccess, 
ProviderSummary: verificationSummary, XEmbedded: verificationDetails}
+       PactLogger.Infof("Verification result retrieved successfully ...")
+       return &RetrieveVerificationResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "Verification 
result retrieved successfully."),
+               Result:   verificationResult,
+       }, nil
+}
+
+func (*BrokerService) PublishVerificationResults(ctx context.Context, in 
*PublishVerificationRequest) (*PublishVerificationResponse, error) {
+       if in == nil || len(in.ProviderId) == 0 || len(in.ConsumerId) == 0 {
+               PactLogger.Errorf(nil, "verification result publish request 
failed: invalid params.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+       tenant := GetDefaultTenantProject()
+       consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
+       if err != nil {
+               PactLogger.Errorf(err, "verification result publish request 
failed, consumerId is %s: query consumer failed.", in.ConsumerId)
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query consumer failed."),
+               }, err
+       }
+       if consumer == nil {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, consumerId is %s: consumer not exist.", in.ConsumerId)
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Consumer does not exist."),
+               }, nil
+       }
+       PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", 
consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
+       // Get consumer participant
+       consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, 
consumer.ServiceName)
+       if err != nil || consumerParticipant == nil {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, consumer participant cannot be searched.", in.ConsumerId)
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"consumer participant cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("Consumer participant found: (%d, %s, %s)", 
consumerParticipant.Id, consumerParticipant.AppId, 
consumerParticipant.ServiceName)
+       // Get version
+       version, err := GetVersion(ctx, tenant, consumer.Version, 
consumerParticipant.Id)
+       if err != nil || version == nil {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, version cannot be searched.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"version cannot be searched."),
+               }, err
+       }
+       PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, 
version.Number, version.ParticipantId, version.Order)
+       key := util.StringJoin([]string{GetBrokerPactKey(tenant), ""}, "/")
+       pacts, err := Store().Pact().Search(ctx,
+               registry.WithStrKey(key),
+               registry.WithPrefix())
+
+       if err != nil || len(pacts.Kvs) == 0 {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, pact cannot be searched.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact cannot be searched."),
+               }, err
+       }
+       pactExists := false
+       for i := 0; i < len(pacts.Kvs); i++ {
+               pact := &Pact{}
+               err = json.Unmarshal(pacts.Kvs[i].Value, &pact)
+               if err != nil {
+                       PactLogger.Errorf(nil, "verification result publish 
request failed, pact cannot be searched.")
+                       return &PublishVerificationResponse{
+                               Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "pact cannot be searched."),
+                       }, err
+               }
+               if pact.Id == in.PactId {
+                       pactExists = true
+               }
+       }
+       if pactExists == false {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, pact does not exists.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact does not exists."),
+               }, err
+       }
+       pactVersion, err := GetPactVersion(ctx, tenant, version.Id, in.PactId)
+       if err != nil || pactVersion == nil {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, pact version cannot be searched.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact version cannot be searched."),
+               }, err
+       }
+       // Check if some verification results already exists
+       key = util.StringJoin([]string{GetBrokerVerificationKey(tenant), 
strconv.Itoa(int(pactVersion.Id))}, "/")
+       verifications, err := Store().Verification().Search(ctx,
+               registry.WithStrKey(key),
+               registry.WithPrefix())
+
+       if err != nil {
+               PactLogger.Errorf(nil, "verification result publish request 
failed, verification result cannot be searched.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"verification result cannot be searched."),
+               }, err
+       }
+       lastNumber := int32(math.MinInt32)
+       if len(verifications.Kvs) != 0 {
+               for i := 0; i < len(verifications.Kvs); i++ {
+                       verification := &Verification{}
+                       err = json.Unmarshal(verifications.Kvs[i].Value, 
&verification)
+                       if err != nil {
+                               PactLogger.Errorf(nil, "verification result 
publish request failed, verification result unmarshall error.")
+                               return &PublishVerificationResponse{
+                                       Response: 
pb.CreateResponse(scerr.ErrInvalidParams, "verification result unmarshall 
error."),
+                               }, err
+                       }
+                       if verification.Number > lastNumber {
+                               lastNumber = verification.Number
+                       }
+               }
+       }
+       if lastNumber < 0 {
+               lastNumber = 0
+       } else {
+               lastNumber++
+       }
+       verificationDate := time.Now().Format(time.RFC3339)
+       verificationKey := GenerateBrokerVerificationKey(tenant, 
pactVersion.Id, lastNumber)
+       id, err := GetData(ctx, GetBrokerLatestVerificationIDKey())
+       verification := &Verification{
+               Id:               int32(id) + 1,
+               Number:           lastNumber,
+               PactVersionId:    pactVersion.Id,
+               Success:          in.Success,
+               ProviderVersion:  in.ProviderApplicationVersion,
+               BuildUrl:         "",
+               VerificationDate: verificationDate,
+       }
+       response, err := CreateVerification(PactLogger, ctx, verificationKey, 
*verification)
+       if err != nil {
+               return response, err
+       }
+       PactLogger.Infof("Verification result inserted: (%d, %d, %d, %t, %s, 
%s, %s)",
+               verification.Id, verification.Number, 
verification.PactVersionId,
+               verification.Success, verification.ProviderVersion, 
verification.BuildUrl, verification.VerificationDate)
+       verificationResponse := &VerificationDetail{
+               ProviderName:               in.ProviderId,
+               ProviderApplicationVersion: verification.ProviderVersion,
+               Success:                    verification.Success,
+               VerificationDate:           verification.VerificationDate,
+       }
+       PactLogger.Infof("Verification result published successfully ...")
+       return &PublishVerificationResponse{
+               Response:     pb.CreateResponse(pb.Response_SUCCESS, 
"Verification result published successfully."),
+               Confirmation: verificationResponse,
+       }, nil
+}
+
+func (*BrokerService) PublishPact(ctx context.Context, in *PublishPactRequest) 
(*PublishPactResponse, error) {
+       if in == nil || len(in.ProviderId) == 0 || len(in.ConsumerId) == 0 || 
len(in.Version) == 0 || len(in.Pact) == 0 {
+               PactLogger.Errorf(nil, "pact publish request failed: invalid 
params.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Request format invalid."),
+               }, nil
+       }
+       tenant := GetDefaultTenantProject()
+
+       provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
+       if err != nil {
+               PactLogger.Errorf(err, "pact publish failed, providerId is %s: 
query provider failed.", in.ProviderId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query provider failed."),
+               }, err
+       }
+       if provider == nil {
+               PactLogger.Errorf(nil, "pact publish failed, providerId is %s: 
provider not exist.", in.ProviderId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider does not exist."),
+               }, nil
+       }
+       PactLogger.Infof("Provider service found: (%s, %s, %s, %s)", 
provider.ServiceId, provider.AppId, provider.ServiceName, provider.Version)
+       consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
+       if err != nil {
+               PactLogger.Errorf(err, "pact publish failed, consumerId is %s: 
query consumer failed.", in.ConsumerId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Query consumer failed."),
+               }, err
+       }
+       if consumer == nil {
+               PactLogger.Errorf(nil, "pact publish failed, consumerId is %s: 
consumer not exist.", in.ConsumerId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Consumer does not exist."),
+               }, nil
+       }
+
+       // check that the consumer has that vesion in the url
+       if strings.Compare(consumer.GetVersion(), in.Version) != 0 {
+               util.Logger().Errorf(nil,
+                       "pact publish failed, version (%s) does not exist for 
consmer", in.Version)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Consumer Version does not exist."),
+               }, nil
+       }
+
+       PactLogger.Infof("Consumer service found: (%s, %s, %s, %s)", 
consumer.ServiceId, consumer.AppId, consumer.ServiceName, consumer.Version)
+       // Get or create provider participant
+       providerParticipantKey := GenerateBrokerParticipantKey(tenant, 
provider.AppId, provider.ServiceName)
+       providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, 
provider.ServiceName)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, provider 
participant cannot be searched.", in.ProviderId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"Provider participant cannot be searched."),
+               }, err
+       }
+       if providerParticipant == nil {
+               id, err := GetData(ctx, GetBrokerLatestParticipantIDKey())
+               providerParticipant = &Participant{Id: int32(id) + 1, AppId: 
provider.AppId, ServiceName: provider.ServiceName}
+               response, err := CreateParticipant(PactLogger, ctx, 
providerParticipantKey, *providerParticipant)
+               if err != nil {
+                       return response, err
+               }
+       }
+       PactLogger.Infof("Provider participant found: (%d, %s, %s)", 
providerParticipant.Id, providerParticipant.AppId, 
providerParticipant.ServiceName)
+       // Get or create consumer participant
+       consumerParticipantKey := GenerateBrokerParticipantKey(tenant, 
consumer.AppId, consumer.ServiceName)
+       consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, 
consumer.ServiceName)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, consumer 
participant cannot be searched.", in.ConsumerId)
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"consumer participant cannot be searched."),
+               }, err
+       }
+       if consumerParticipant == nil {
+               id, err := GetData(ctx, GetBrokerLatestParticipantIDKey())
+               consumerParticipant = &Participant{Id: int32(id) + 1, AppId: 
consumer.AppId, ServiceName: consumer.ServiceName}
+               response, err := CreateParticipant(PactLogger, ctx, 
consumerParticipantKey, *consumerParticipant)
+               if err != nil {
+                       return response, err
+               }
+       }
+       PactLogger.Infof("Consumer participant found: (%d, %s, %s)", 
consumerParticipant.Id, consumerParticipant.AppId, 
consumerParticipant.ServiceName)
+       // Get or create version
+       versionKey := GenerateBrokerVersionKey(tenant, in.Version, 
consumerParticipant.Id)
+       version, err := GetVersion(ctx, tenant, in.Version, 
consumerParticipant.Id)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, version cannot be 
searched.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"version cannot be searched."),
+               }, err
+       }
+       if version == nil {
+               order := GetLastestVersionNumberForParticipant(ctx, tenant, 
consumerParticipant.Id)
+               PactLogger.Infof("Old version order: %d", order)
+               order++
+               id, err := GetData(ctx, GetBrokerLatestVersionIDKey())
+               version = &Version{Id: int32(id) + 1, Number: in.Version, 
ParticipantId: consumerParticipant.Id, Order: order}
+               response, err := CreateVersion(PactLogger, ctx, versionKey, 
*version)
+               if err != nil {
+                       return response, err
+               }
+       }
+       PactLogger.Infof("Version found/created: (%d, %s, %d, %d)", version.Id, 
version.Number, version.ParticipantId, version.Order)
+       // Get or create pact
+       sha1 := sha1.Sum(in.Pact)
+       var sha []byte = sha1[:]
+       pactKey := GenerateBrokerPactKey(tenant, consumerParticipant.Id, 
providerParticipant.Id, sha)
+       pact, err := GetPact(ctx, tenant, consumerParticipant.Id, 
providerParticipant.Id, sha)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact cannot be 
searched.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact cannot be searched."),
+               }, err
+       }
+       if pact == nil {
+               id, err := GetData(ctx, GetBrokerLatestPactIDKey())
+               pact = &Pact{Id: int32(id) + 1, ConsumerParticipantId: 
consumerParticipant.Id,
+                       ProviderParticipantId: providerParticipant.Id, Sha: 
sha, Content: in.Pact}
+               response, err := CreatePact(PactLogger, ctx, pactKey, *pact)
+               if err != nil {
+                       return response, err
+               }
+       }
+       PactLogger.Infof("Pact found/created: (%d, %d, %d, %s)", pact.Id, 
pact.ConsumerParticipantId, pact.ProviderParticipantId, pact.Sha)
+       // Get or create pact version
+       pactVersionKey := GenerateBrokerPactVersionKey(tenant, version.Id, 
pact.Id)
+       pactVersion, err := GetPactVersion(ctx, tenant, version.Id, pact.Id)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact version 
cannot be searched.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInvalidParams, 
"pact version cannot be searched."),
+               }, err
+       }
+       if pactVersion == nil {
+               id, err := GetData(ctx, GetBrokerLatestPactVersionIDKey())
+               pactVersion = &PactVersion{Id: int32(id) + 1, VersionId: 
version.Id, PactId: pact.Id, ProviderParticipantId: providerParticipant.Id}
+               response, err := CreatePactVersion(PactLogger, ctx, 
pactVersionKey, *pactVersion)
+               if err != nil {
+                       return response, err
+               }
+       }
+       PactLogger.Infof("PactVersion found/create: (%d, %d, %d, %d)", 
pactVersion.Id, pactVersion.VersionId, pactVersion.PactId, 
pactVersion.ProviderParticipantId)
+       PactLogger.Infof("Pact published successfully ...")
+       return &PublishPactResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "Pact 
published successfully."),
+       }, nil
+}
diff --git a/server/broker/service_test.go b/server/broker/service_test.go
new file mode 100644
index 0000000..516b8c3
--- /dev/null
+++ b/server/broker/service_test.go
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "fmt"
+
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
+       "github.com/apache/incubator-servicecomb-service-center/server/core"
+       pb 
"github.com/apache/incubator-servicecomb-service-center/server/core/proto"
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+       "golang.org/x/net/context"
+)
+
+const (
+       TEST_BROKER_NO_SERVICE_ID      = "noServiceId"
+       TEST_BROKER_NO_VERSION         = "noVersion"
+       TEST_BROKER_TOO_LONG_SERVICEID = 
"addasdfasaddasdfasaddasdfasaddasdfasaddasdfasaddasdfasaddasdfasadafd"
+       //Consumer
+       TEST_BROKER_CONSUMER_VERSION = "4.0.0"
+       TEST_BROKER_CONSUMER_NAME    = "broker_name_consumer"
+       TEST_BROKER_CONSUMER_APP     = "broker_group_consumer"
+       //Provider
+       TEST_BROKER_PROVIDER_VERSION = "3.0.0"
+       TEST_BROKER_PROVIDER_NAME    = "broker_name_provider"
+       TEST_BROKER_PROVIDER_APP     = "broker_group_provider"
+)
+
+var brokerResource = BrokerServiceAPI
+var serviceResource = core.ServiceAPI
+var consumerServiceId string
+var providerServiceId string
+
+var _ = Describe("BrokerController", func() {
+       Describe("brokerDependency", func() {
+               Context("normal", func() {
+                       It("PublishPact", func() {
+                               fmt.Println("UT===========PublishPact")
+
+                               //(1) create consumer service
+                               resp, err := 
serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+                                       Service: &pb.MicroService{
+                                               ServiceName: 
TEST_BROKER_CONSUMER_NAME,
+                                               AppId:       
TEST_BROKER_CONSUMER_APP,
+                                               Version:     
TEST_BROKER_CONSUMER_VERSION,
+                                               Level:       "FRONT",
+                                               Schemas: []string{
+                                                       "xxxxxxxx",
+                                               },
+                                               Status: "UP",
+                                       },
+                               })
+
+                               Expect(err).To(BeNil())
+                               consumerServiceId = resp.ServiceId
+                               
Expect(resp.GetResponse().Code).To(Equal(pb.Response_SUCCESS))
+
+                               //(2) create provider service
+                               resp, err = 
serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+                                       Service: &pb.MicroService{
+                                               ServiceName: 
TEST_BROKER_PROVIDER_NAME,
+                                               AppId:       
TEST_BROKER_PROVIDER_APP,
+                                               Version:     
TEST_BROKER_PROVIDER_VERSION,
+                                               Level:       "FRONT",
+                                               Schemas: []string{
+                                                       "xxxxxxxx",
+                                               },
+                                               Status:     "UP",
+                                               Properties: 
map[string]string{"allowCrossApp": "true"},
+                                       },
+                               })
+                               Expect(err).To(BeNil())
+                               providerServiceId = resp.ServiceId
+                               
Expect(resp.GetResponse().Code).To(Equal(pb.Response_SUCCESS))
+
+                               //(3) publish a pact between two services
+                               respPublishPact, err := 
brokerResource.PublishPact(getContext(),
+                                       &PublishPactRequest{
+                                               ProviderId: providerServiceId,
+                                               ConsumerId: consumerServiceId,
+                                               Version:    
TEST_BROKER_CONSUMER_VERSION,
+                                               Pact:       []byte("hello"),
+                                       })
+
+                               Expect(err).To(BeNil())
+                               
Expect(respPublishPact.GetResponse().Code).To(Equal(pb.Response_SUCCESS))
+                       })
+
+                       It("PublishPact-noProviderServiceId", func() {
+                               fmt.Println("UT===========PublishPact, no 
provider serviceID")
+
+                               //publish a pact between two services
+                               respPublishPact, _ := 
brokerResource.PublishPact(getContext(), &PublishPactRequest{
+                                       ProviderId: TEST_BROKER_NO_SERVICE_ID,
+                                       ConsumerId: consumerServiceId,
+                                       Version:    
TEST_BROKER_CONSUMER_VERSION,
+                                       Pact:       []byte("hello"),
+                               })
+
+                               
Expect(respPublishPact.GetResponse().Code).ToNot(Equal(pb.Response_SUCCESS))
+                       })
+
+                       It("PublishPact-noConumerServiceId", func() {
+                               fmt.Println("UT===========PublishPact, no 
consumer serviceID")
+
+                               //publish a pact between two services
+                               respPublishPact, _ := 
brokerResource.PublishPact(getContext(), &PublishPactRequest{
+                                       ProviderId: providerServiceId,
+                                       ConsumerId: TEST_BROKER_NO_SERVICE_ID,
+                                       Version:    
TEST_BROKER_CONSUMER_VERSION,
+                                       Pact:       []byte("hello"),
+                               })
+
+                               
Expect(respPublishPact.GetResponse().Code).ToNot(Equal(pb.Response_SUCCESS))
+                       })
+
+                       It("PublishPact-noConumerVersion", func() {
+                               fmt.Println("UT===========PublishPact, no 
consumer Version")
+
+                               //publish a pact between two services
+                               respPublishPact, _ := 
brokerResource.PublishPact(getContext(), &PublishPactRequest{
+                                       ProviderId: providerServiceId,
+                                       ConsumerId: consumerServiceId,
+                                       Version:    TEST_BROKER_NO_VERSION,
+                                       Pact:       []byte("hello"),
+                               })
+
+                               
Expect(respPublishPact.GetResponse().Code).ToNot(Equal(pb.Response_SUCCESS))
+                       })
+
+                       It("GetBrokerHome", func() {
+                               fmt.Println("UT===========GetBrokerHome")
+
+                               respGetHome, _ := 
brokerResource.GetBrokerHome(getContext(), &BaseBrokerRequest{
+                                       HostAddress: "localhost",
+                                       Scheme:      "http",
+                               })
+
+                               Expect(respGetHome).NotTo(BeNil())
+
+                       })
+
+                       It("GetBrokerAllProviderPacts", func() {
+                               
fmt.Println("UT===========GetBrokerAllProviderPacts")
+
+                               respGetAllProviderPacts, _ := 
brokerResource.GetAllProviderPacts(getContext(),
+                                       &GetAllProviderPactsRequest{
+                                               ProviderId: providerServiceId,
+                                               BaseUrl: &BaseBrokerRequest{
+                                                       HostAddress: 
"localhost",
+                                                       Scheme:      "http",
+                                               }})
+
+                               Expect(respGetAllProviderPacts).NotTo(BeNil())
+                               
Expect(respGetAllProviderPacts.GetResponse().Code).To(Equal(pb.Response_SUCCESS))
+                       })
+
+                       It("GetBrokerPactsOfProvider", func() {
+                               
fmt.Println("UT===========GetBrokerPactsOfProvider")
+
+                               respGetAllProviderPacts, _ := 
brokerResource.GetPactsOfProvider(getContext(),
+                                       &GetProviderConsumerVersionPactRequest{
+                                               ProviderId: providerServiceId,
+                                               ConsumerId: consumerServiceId,
+                                               Version:    
TEST_BROKER_CONSUMER_VERSION,
+                                               BaseUrl: &BaseBrokerRequest{
+                                                       HostAddress: 
"localhost",
+                                                       Scheme:      "http",
+                                               }})
+
+                               Expect(respGetAllProviderPacts).NotTo(BeNil())
+                               
Expect(respGetAllProviderPacts.GetResponse().Code).To(Equal(pb.Response_SUCCESS))
+                       })
+
+               })
+       })
+})
+
+func getContext() context.Context {
+       ctx := context.TODO()
+       ctx = util.SetContext(ctx, "domain", "default")
+       ctx = util.SetContext(ctx, "project", "default")
+       ctx = util.SetContext(ctx, "noCache", "1")
+       return ctx
+}
diff --git a/server/broker/store.go b/server/broker/store.go
new file mode 100644
index 0000000..0cdddc5
--- /dev/null
+++ b/server/broker/store.go
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "sync"
+
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
+       sstore 
"github.com/apache/incubator-servicecomb-service-center/server/core/backend/store"
+)
+
+const (
+       PARTICIPANT sstore.StoreType = iota
+       VERSION
+       PACT
+       PACT_VERSION
+       PACT_TAG
+       VERIFICATION
+       PACT_LATEST
+       typeEnd
+)
+
+var TypeNames = []string{
+       PARTICIPANT:  "PARTICIPANT",
+       VERSION:      "VERSION",
+       PACT:         "PACT",
+       PACT_VERSION: "PACT_VERSION",
+       PACT_TAG:     "PACT_TAG",
+       VERIFICATION: "VERIFICATION",
+       PACT_LATEST:  "PACT_LATEST",
+}
+
+var TypeRoots = map[sstore.StoreType]string{
+       PARTICIPANT:  GetBrokerParticipantKey(""),
+       VERSION:      GetBrokerVersionKey(""),
+       PACT:         GetBrokerPactKey(""),
+       PACT_VERSION: GetBrokerPactVersionKey(""),
+       PACT_TAG:     GetBrokerTagKey(""),
+       VERIFICATION: GetBrokerVerificationKey(""),
+       PACT_LATEST:  GetBrokerLatestKey(""),
+}
+
+var store = &BKvStore{}
+
+func Store() *BKvStore {
+       return store
+}
+
+func (s *BKvStore) StoreSize(t sstore.StoreType) int {
+       return 100
+}
+
+func (s *BKvStore) newStore(t sstore.StoreType, opts 
...sstore.KvCacherCfgOption) {
+       opts = append(opts,
+               sstore.WithKey(TypeRoots[t]),
+               sstore.WithInitSize(s.StoreSize(t)),
+       )
+       s.newIndexer(t, sstore.NewKvCacher(opts...))
+}
+
+func (s *BKvStore) store() {
+       for t := sstore.StoreType(0); t != typeEnd; t++ {
+               s.newStore(t)
+       }
+       for _, i := range s.bindexers {
+               <-i.Ready()
+       }
+       util.SafeCloseChan(s.bready)
+
+       util.Logger().Debugf("all indexers are ready")
+}
+
+func init() {
+       store.Initialize()
+       store.Run()
+       store.Ready()
+}
+
+type BKvStore struct {
+       *sstore.KvStore
+       bindexers map[sstore.StoreType]*sstore.Indexer
+       block     sync.RWMutex
+       bready    chan struct{}
+       bisClose  bool
+}
+
+func (s *BKvStore) Initialize() {
+       s.KvStore = sstore.Store()
+       s.KvStore.Initialize()
+       s.bindexers = make(map[sstore.StoreType]*sstore.Indexer)
+       s.bready = make(chan struct{})
+
+       for i := sstore.StoreType(0); i != typeEnd; i++ {
+               store.newNullStore(i)
+       }
+}
+
+func (s *BKvStore) newNullStore(t sstore.StoreType) {
+       s.newIndexer(t, sstore.NullCacher)
+}
+
+func (s *BKvStore) newIndexer(t sstore.StoreType, cacher sstore.Cacher) {
+       indexer := sstore.NewCacheIndexer(t, cacher)
+       s.bindexers[t] = indexer
+       indexer.Run()
+}
+
+func (s *BKvStore) Run() {
+       go s.store()
+}
+
+func (s *BKvStore) Ready() <-chan struct{} {
+       return s.bready
+}
+
+func (s *BKvStore) Participant() *sstore.Indexer {
+       return s.bindexers[PARTICIPANT]
+}
+
+func (s *BKvStore) Version() *sstore.Indexer {
+       return s.bindexers[VERSION]
+}
+
+func (s *BKvStore) Pact() *sstore.Indexer {
+       return s.bindexers[PACT]
+}
+
+func (s *BKvStore) PactVersion() *sstore.Indexer {
+       return s.bindexers[PACT_VERSION]
+}
+
+func (s *BKvStore) PactTag() *sstore.Indexer {
+       return s.bindexers[PACT_TAG]
+}
+
+func (s *BKvStore) Verification() *sstore.Indexer {
+       return s.bindexers[VERIFICATION]
+}
+
+func (s *BKvStore) PactLatest() *sstore.Indexer {
+       return s.bindexers[PACT_LATEST]
+}
diff --git a/server/broker/util.go b/server/broker/util.go
new file mode 100644
index 0000000..23e98ca
--- /dev/null
+++ b/server/broker/util.go
@@ -0,0 +1,680 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package broker
+
+import (
+       "context"
+       "encoding/json"
+       "errors"
+       "math"
+       "net/url"
+       "strconv"
+       "strings"
+
+       "github.com/ServiceComb/paas-lager"
+       
"github.com/ServiceComb/paas-lager/third_party/forked/cloudfoundry/lager"
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
+       backend 
"github.com/apache/incubator-servicecomb-service-center/server/core/backend"
+       pb 
"github.com/apache/incubator-servicecomb-service-center/server/core/proto"
+       scerr 
"github.com/apache/incubator-servicecomb-service-center/server/error"
+       
"github.com/apache/incubator-servicecomb-service-center/server/infra/registry"
+       serviceUtil 
"github.com/apache/incubator-servicecomb-service-center/server/service/util"
+)
+
+var PactLogger lager.Logger
+
+const (
+       BROKER_HOME_URL                      = "/"
+       BROKER_PARTICIPANTS_URL              = "/participants"
+       BROKER_PARTICIPANT_URL               = "/participants/:participantId"
+       BROKER_PARTY_VERSIONS_URL            = 
"/participants/:participantId/versions"
+       BROKER_PARTY_LATEST_VERSION_URL      = 
"/participants/:participantId/versions/latest"
+       BROKER_PARTY_VERSION_URL             = 
"/participants/:participantId/versions/:number"
+       BROKER_PROVIDER_URL                  = "/pacts/provider"
+       BROKER_PROVIDER_LATEST_PACTS_URL     = 
"/pacts/provider/:providerId/latest"
+       BROKER_PROVIDER_LATEST_PACTS_TAG_URL = 
"/pacts/provider/:providerId/latest/:tag"
+       BROKER_PACTS_LATEST_URL              = "/pacts/latest"
+
+       BROKER_PUBLISH_URL              = 
"/pacts/provider/:providerId/consumer/:consumerId/version/:number"
+       BROKER_PUBLISH_VERIFICATION_URL = 
"/pacts/provider/:providerId/consumer/:consumerId/pact-version/:pact/verification-results"
+       BROKER_WEBHOOHS_URL             = "/webhooks"
+
+       BROKER_CURIES_URL = "/doc/:rel"
+)
+
+var brokerAPILinksValues = map[string]string{
+       "self":                              BROKER_HOME_URL,
+       "pb:publish-pact":                   BROKER_PUBLISH_URL,
+       "pb:latest-pact-versions":           BROKER_PACTS_LATEST_URL,
+       "pb:pacticipants":                   BROKER_PARTICIPANTS_URL,
+       "pb:latest-provider-pacts":          BROKER_PROVIDER_LATEST_PACTS_URL,
+       "pb:latest-provider-pacts-with-tag": 
BROKER_PROVIDER_LATEST_PACTS_TAG_URL,
+       "pb:webhooks":                       BROKER_WEBHOOHS_URL,
+}
+
+var brokerAPILinksTempl = map[string]bool{
+       "self":                              false,
+       "pb:publish-pact":                   true,
+       "pb:latest-pact-versions":           false,
+       "pb:pacticipants":                   false,
+       "pb:latest-provider-pacts":          true,
+       "pb:latest-provider-pacts-with-tag": true,
+       "pb:webhooks":                       false,
+}
+
+var brokerAPILinksTitles = map[string]string{
+       "self":                              "Index",
+       "pb:publish-pact":                   "Publish a pact",
+       "pb:latest-pact-versions":           "Latest pact versions",
+       "pb:pacticipants":                   "Pacticipants",
+       "pb:latest-provider-pacts":          "Latest pacts by provider",
+       "pb:latest-provider-pacts-with-tag": "Latest pacts by provider with a 
specified tag",
+       "pb:webhooks":                       "Webhooks",
+}
+
+func init() {
+       //define Broker logger
+       stlager.Init(stlager.Config{
+               LoggerLevel:   "INFO",
+               LoggerFile:    "broker_srvc.log",
+               EnableRsyslog: false,
+       })
+       PactLogger = stlager.NewLogger("broker_srvc")
+}
+
+func GetDefaultTenantProject() string {
+       return util.StringJoin([]string{"default", "default"}, "/")
+}
+
+//GenerateBrokerAPIPath creates the API link from the constant template
+func GenerateBrokerAPIPath(scheme string, host string, apiPath string,
+       replacer *strings.Replacer) string {
+       genPath := url.URL{
+               Scheme: scheme,
+               Host:   host,
+               Path:   apiPath,
+       }
+       if replacer != nil {
+               return replacer.Replace(genPath.String())
+       }
+       return genPath.String()
+}
+
+//GetBrokerHomeLinksAPIS return the generated Home links
+func GetBrokerHomeLinksAPIS(scheme string, host string, apiKey string) string {
+       return GenerateBrokerAPIPath(scheme, host, brokerAPILinksValues[apiKey],
+               strings.NewReplacer(":providerId", "{provider}",
+                       ":consumerId", "{consumer}",
+                       ":number", "{consumerApplicationVersion}",
+                       ":tag", "{tag}"))
+}
+
+//CreateBrokerHomeResponse create the templated broker home response
+func CreateBrokerHomeResponse(host string, scheme string) *BrokerHomeResponse {
+
+       var apiEntries map[string]*BrokerAPIInfoEntry
+       apiEntries = make(map[string]*BrokerAPIInfoEntry)
+
+       for k := range brokerAPILinksValues {
+               apiEntries[k] = &BrokerAPIInfoEntry{
+                       Href:      GetBrokerHomeLinksAPIS(scheme, host, k),
+                       Title:     brokerAPILinksTitles[k],
+                       Templated: brokerAPILinksTempl[k],
+               }
+       }
+
+       curies := []*BrokerAPIInfoEntry{}
+       curies = append(curies, &BrokerAPIInfoEntry{
+               Name: "pb",
+               Href: GenerateBrokerAPIPath(scheme, host, BROKER_CURIES_URL,
+                       strings.NewReplacer(":rel", "{rel}")),
+       })
+
+       return &BrokerHomeResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "Broker 
Home."),
+               XLinks:   apiEntries,
+               Curies:   curies,
+       }
+}
+
+//GetBrokerHomeResponse gets the homeResponse from cache if it exists
+func GetBrokerHomeResponse(host string, scheme string) *BrokerHomeResponse {
+       brokerResp := CreateBrokerHomeResponse(host, scheme)
+       if brokerResp == nil {
+               return nil
+       }
+       return brokerResp
+}
+
+//GetBrokerParticipantUtils returns the participant from ETCD
+func GetBrokerParticipantUtils(ctx context.Context, tenant string, appId 
string,
+       serviceName string, opts ...registry.PluginOpOption) (*Participant, 
error) {
+
+       key := GenerateBrokerParticipantKey(tenant, appId, serviceName)
+       opts = append(opts, registry.WithStrKey(key))
+       participants, err := Store().Participant().Search(ctx, opts...)
+
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, participant with, 
could not be searched.")
+               return nil, err
+       }
+
+       if len(participants.Kvs) == 0 {
+               PactLogger.Info("GetParticipant found no participant")
+               return nil, nil
+       }
+
+       participant := &Participant{}
+       err = json.Unmarshal(participants.Kvs[0].Value, participant)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("GetParticipant: (%d, %s, %s)", participant.Id, 
participant.AppId,
+               participant.ServiceName)
+       return participant, nil
+}
+
+//GetBrokerParticipantFromServiceId returns the participant and the service 
from ETCD
+func GetBrokerParticipantFromServiceId(ctx context.Context, serviceId string) 
(*Participant,
+       *pb.MicroService, error, error) {
+
+       tenant := GetDefaultTenantProject()
+       serviceParticipant, err := serviceUtil.GetService(ctx, tenant, 
serviceId)
+       if err != nil {
+               PactLogger.Errorf(err,
+                       "get participant failed, serviceId is %s: query 
provider failed.", serviceId)
+               return nil, nil, nil, err
+       }
+       if serviceParticipant == nil {
+               PactLogger.Errorf(nil,
+                       "get participant failed, serviceId is %s: service not 
exist.", serviceId)
+               return nil, nil, nil, errors.New("get participant, serviceId 
not exist.")
+       }
+       // Get or create provider participant
+       participant, errBroker := GetBrokerParticipantUtils(ctx, tenant, 
serviceParticipant.AppId,
+               serviceParticipant.ServiceName)
+       if errBroker != nil {
+               PactLogger.Errorf(errBroker,
+                       "get participant failed, serviceId %s: query 
participant failed.", serviceId)
+               return nil, serviceParticipant, errBroker, err
+       }
+       if participant == nil {
+               PactLogger.Errorf(nil,
+                       "get participant failed, particpant does not exist for 
serviceId %s", serviceId)
+               return nil, serviceParticipant, errors.New("particpant does not 
exist for serviceId."), err
+       }
+
+       return participant, serviceParticipant, errBroker, nil
+}
+
+//GetBrokerParticipantFromService returns the participant given the 
microservice
+func GetBrokerParticipantFromService(ctx context.Context,
+       microservice *pb.MicroService) (*Participant, error) {
+       if microservice == nil {
+               return nil, nil
+       }
+       tenant := GetDefaultTenantProject()
+       participant, errBroker := GetBrokerParticipantUtils(ctx, tenant, 
microservice.AppId,
+               microservice.ServiceName)
+       if errBroker != nil {
+               PactLogger.Errorf(errBroker,
+                       "get participant failed, serviceId %s: query 
participant failed.",
+                       microservice.ServiceId)
+               return nil, errBroker
+       }
+       return participant, errBroker
+}
+
+func GetParticipant(ctx context.Context, domain string, appId string,
+       serviceName string) (*Participant, error) {
+       key := GenerateBrokerParticipantKey(domain, appId, serviceName)
+       participants, err := Store().Participant().Search(ctx, 
registry.WithStrKey(key))
+       if err != nil {
+               return nil, err
+       }
+       if len(participants.Kvs) == 0 {
+               PactLogger.Info("GetParticipant found no participant")
+               return nil, nil
+       }
+       participant := &Participant{}
+       err = json.Unmarshal(participants.Kvs[0].Value, participant)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("GetParticipant: (%d, %s, %s)", participant.Id, 
participant.AppId, participant.ServiceName)
+       return participant, nil
+}
+
+func GetVersion(ctx context.Context, domain string, number string,
+       participantId int32) (*Version, error) {
+       key := GenerateBrokerVersionKey(domain, number, participantId)
+       versions, err := Store().Version().Search(ctx, registry.WithStrKey(key))
+       if err != nil {
+               return nil, err
+       }
+       if len(versions.Kvs) == 0 {
+               return nil, nil
+       }
+       version := &Version{}
+       err = json.Unmarshal(versions.Kvs[0].Value, version)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("GetVersion: (%d, %s, %d, %d)", version.Id, 
version.Number, version.ParticipantId, version.Order)
+       return version, nil
+}
+
+func GetPact(ctx context.Context, domain string, consumerParticipantId int32, 
producerParticipantId int32, sha []byte) (*Pact, error) {
+       key := GenerateBrokerPactKey(domain, consumerParticipantId, 
producerParticipantId, sha)
+       versions, err := Store().Pact().Search(ctx, registry.WithStrKey(key))
+       if err != nil {
+               return nil, err
+       }
+       if len(versions.Kvs) == 0 {
+               return nil, nil
+       }
+       pact := &Pact{}
+       err = json.Unmarshal(versions.Kvs[0].Value, pact)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("GetPact: (%d, %d, %d, %s, %s)", pact.Id, 
pact.ConsumerParticipantId, pact.ProviderParticipantId, string(pact.Sha), 
string(pact.Content))
+       return pact, nil
+}
+
+func GetPactVersion(ctx context.Context, domain string, versionId int32,
+       pactId int32) (*PactVersion, error) {
+       key := GenerateBrokerPactVersionKey(domain, versionId, pactId)
+       versions, err := Store().PactVersion().Search(ctx, 
registry.WithStrKey(key))
+       if err != nil {
+               return nil, err
+       }
+       if len(versions.Kvs) == 0 {
+               return nil, nil
+       }
+       pactVersion := &PactVersion{}
+       err = json.Unmarshal(versions.Kvs[0].Value, pactVersion)
+       if err != nil {
+               return nil, err
+       }
+       PactLogger.Infof("GetPactVersion: (%d, %d, %d, %d)", pactVersion.Id, 
pactVersion.VersionId, pactVersion.PactId, pactVersion.ProviderParticipantId)
+       return pactVersion, nil
+}
+
+func GetData(ctx context.Context, key string) (int, error) {
+       values, err := Store().PactLatest().Search(ctx, 
registry.WithStrKey(key))
+       if err != nil {
+               return -1, err
+       }
+       if len(values.Kvs) == 0 {
+               return -1, nil
+       }
+       id, err := strconv.Atoi(string(values.Kvs[0].Value))
+       if err != nil {
+               return -1, err
+       }
+       return id, nil
+}
+
+func StoreData(ctx context.Context, key string, value string) error {
+       _, err := backend.Registry().Do(ctx, registry.PUT,
+               registry.WithStrKey(key),
+               registry.WithValue([]byte(value)))
+       return err
+}
+
+func CreateParticipant(pactLogger lager.Logger, ctx context.Context, 
participantKey string, participant Participant) (*PublishPactResponse, error) {
+       data, err := json.Marshal(participant)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, participant cannot 
be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"participant cannot be created."),
+               }, err
+       }
+
+       _, err = backend.Registry().Do(ctx, registry.PUT,
+               registry.WithStrKey(participantKey),
+               registry.WithValue(data))
+
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, participant cannot 
be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"participant cannot be created."),
+               }, err
+       }
+
+       k := GetBrokerLatestParticipantIDKey()
+       v := strconv.Itoa(int(participant.Id))
+       PactLogger.Infof("Inserting (%s, %s)", k, v)
+       err = StoreData(ctx, k, v)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, participant cannot 
be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"participant cannot be created."),
+               }, err
+       }
+       PactLogger.Infof("Participant created for key: %s", participantKey)
+       return nil, nil
+}
+
+func CreateVersion(pactLogger lager.Logger, ctx context.Context, versionKey 
string,
+       version Version) (*PublishPactResponse, error) {
+       data, err := json.Marshal(version)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, version cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "version 
cannot be created."),
+               }, err
+       }
+
+       _, err = backend.Registry().Do(ctx, registry.PUT,
+               registry.WithStrKey(versionKey),
+               registry.WithValue(data))
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, version cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "version 
cannot be created."),
+               }, err
+       }
+       k := GetBrokerLatestVersionIDKey()
+       v := strconv.Itoa(int(version.Id))
+       PactLogger.Infof("Inserting (%s, %s)", k, v)
+       err = StoreData(ctx, k, v)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, version cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "version 
cannot be created."),
+               }, err
+       }
+       PactLogger.Infof("Version created for key: %s", versionKey)
+       return nil, nil
+}
+
+func CreatePact(pactLogger lager.Logger, ctx context.Context,
+       pactKey string, pact Pact) (*PublishPactResponse, error) {
+       data, err := json.Marshal(pact)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
cannot be created."),
+               }, err
+       }
+
+       _, err = backend.Registry().Do(ctx,
+               registry.PUT,
+               registry.WithStrKey(pactKey),
+               registry.WithValue(data))
+
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
cannot be created."),
+               }, err
+       }
+       k := GetBrokerLatestPactIDKey()
+       v := strconv.Itoa(int(pact.Id))
+       PactLogger.Infof("Inserting (%s, %s)", k, v)
+       err = StoreData(ctx, k, v)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact cannot be 
created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
cannot be created."),
+               }, err
+       }
+       PactLogger.Infof("Pact created for key: %s", pactKey)
+       return nil, nil
+}
+
+func CreatePactVersion(pactLogger lager.Logger, ctx context.Context, 
pactVersionKey string, pactVersion PactVersion) (*PublishPactResponse, error) {
+       data, err := json.Marshal(pactVersion)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact version 
cannot be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
version cannot be created."),
+               }, err
+       }
+
+       _, err = backend.Registry().Do(ctx,
+               registry.PUT, registry.WithValue(data), 
registry.WithStrKey(pactVersionKey))
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact version 
cannot be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
version cannot be created."),
+               }, err
+       }
+       k := GetBrokerLatestPactVersionIDKey()
+       v := strconv.Itoa(int(pactVersion.Id))
+       PactLogger.Infof("Inserting (%s, %s)", k, v)
+       err = StoreData(ctx, k, v)
+       if err != nil {
+               PactLogger.Errorf(nil, "pact publish failed, pact version 
cannot be created.")
+               return &PublishPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
version cannot be created."),
+               }, err
+       }
+       PactLogger.Infof("Pact version created for key: %s", pactVersionKey)
+       return nil, nil
+}
+
+func CreateVerification(pactLogger lager.Logger, ctx context.Context,
+       verificationKey string, verification Verification) 
(*PublishVerificationResponse, error) {
+       data, err := json.Marshal(verification)
+       if err != nil {
+               PactLogger.Errorf(nil, "verification result publish failed, 
verification result marshal error.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"verification result marshal error."),
+               }, err
+       }
+
+       _, err = backend.Registry().Do(ctx, registry.PUT,
+               registry.WithStrKey(verificationKey),
+               registry.WithValue(data))
+       if err != nil {
+               PactLogger.Errorf(nil, "verification result publish failed, 
verification result cannot be created.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"verification result cannot be created."),
+               }, err
+       }
+       k := GetBrokerLatestVerificationIDKey()
+       v := strconv.Itoa(int(verification.Id))
+       PactLogger.Infof("Inserting (%s, %s)", k, v)
+       err = StoreData(ctx, k, v)
+       if err != nil {
+               PactLogger.Errorf(nil, "verification result publish failed, 
verification result cannot be created.")
+               return &PublishVerificationResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"verification result cannot be created."),
+               }, err
+       }
+       PactLogger.Infof("Verification result created for key: %s", 
verificationKey)
+       return nil, nil
+}
+
+func GetLastestVersionNumberForParticipant(ctx context.Context,
+       tenant string, participantId int32) int32 {
+       key := util.StringJoin([]string{
+               GetBrokerVersionKey(tenant), ""}, "/")
+       versions, err := Store().Version().Search(ctx,
+               registry.WithStrKey(key),
+               registry.WithPrefix())
+
+       if err != nil || len(versions.Kvs) == 0 {
+               return -1
+       }
+       order := int32(math.MinInt32)
+       for i := 0; i < len(versions.Kvs); i++ {
+               version := &Version{}
+               err = json.Unmarshal(versions.Kvs[i].Value, &version)
+               if err != nil {
+                       return -1
+               }
+               if version.ParticipantId != participantId {
+                       continue
+               }
+               if version.Order > order {
+                       order = version.Order
+               }
+       }
+       return order
+}
+
+func RetrieveProviderConsumerPact(ctx context.Context,
+       in *GetProviderConsumerVersionPactRequest) 
(*GetProviderConsumerVersionPactResponse, int32, error) {
+       if in == nil || len(in.ProviderId) == 0 || len(in.ConsumerId) == 0 || 
len(in.Version) == 0 {
+               PactLogger.Errorf(nil, "pact retrieve request failed: invalid 
params.")
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "Request 
format invalid."),
+               }, -1, nil
+       }
+       tenant := GetDefaultTenantProject()
+       // Get provider microservice
+       provider, err := serviceUtil.GetService(ctx, tenant, in.ProviderId)
+       if err != nil {
+               PactLogger.Errorf(err, "pact retrieve failed, providerId is %s: 
query provider failed.", in.ProviderId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "Query 
provider failed."),
+               }, -1, err
+       }
+       if provider == nil {
+               PactLogger.Errorf(nil, "pact retrieve failed, providerId is %s: 
provider not exist.", in.ProviderId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"Provider does not exist."),
+               }, -1, nil
+       }
+       // Get consumer microservice
+       consumer, err := serviceUtil.GetService(ctx, tenant, in.ConsumerId)
+       if err != nil {
+               PactLogger.Errorf(err, "pact retrieve failed, consumerId is %s: 
query consumer failed.", in.ConsumerId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "Query 
consumer failed."),
+               }, -1, err
+       }
+       if consumer == nil {
+               PactLogger.Errorf(nil, "pact retrieve failed, consumerId is %s: 
consumer not exist.", in.ConsumerId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"Consumer does not exist."),
+               }, -1, nil
+       }
+       // Get provider participant
+       //providerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, 
provider.AppId, provider.ServiceName)
+       providerParticipant, err := GetParticipant(ctx, tenant, provider.AppId, 
provider.ServiceName)
+       if err != nil || providerParticipant == nil {
+               PactLogger.Errorf(nil, "pact retrieve failed, provider 
participant %s cannot be searched.", in.ProviderId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"Provider participant cannot be searched."),
+               }, -1, err
+       }
+       // Get consumer participant
+       //consumerParticipantKey := apt.GenerateBrokerParticipantKey(tenant, 
consumer.AppId, consumer.ServiceName)
+       consumerParticipant, err := GetParticipant(ctx, tenant, consumer.AppId, 
consumer.ServiceName)
+       if err != nil || consumerParticipant == nil {
+               PactLogger.Errorf(nil, "pact retrieve failed, consumer 
participant %s cannot be searched.", in.ConsumerId)
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, 
"consumer participant cannot be searched."),
+               }, -1, err
+       }
+       // Get or create version
+       //versionKey := apt.GenerateBrokerVersionKey(tenant, in.Version, 
consumerParticipant.Id)
+       version, err := GetVersion(ctx, tenant, in.Version, 
consumerParticipant.Id)
+       if err != nil || version == nil {
+               PactLogger.Errorf(nil, "pact retrieve failed, version cannot be 
searched.")
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "version 
cannot be searched."),
+               }, -1, err
+       }
+       // Get all pactversions and filter using the provider participant id
+       pactVersionKey := util.StringJoin([]string{
+               GetBrokerPactVersionKey(tenant),
+               strconv.Itoa(int(version.Id))},
+               "/")
+       pactVersions, err := Store().PactVersion().Search(ctx,
+               registry.WithPrefix(),
+               registry.WithStrKey(pactVersionKey))
+
+       if err != nil {
+               return nil, -1, err
+       }
+       if len(pactVersions.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPact] No pact version found, 
sorry")
+               return nil, -1, nil
+       }
+       pactIds := make(map[int32]int32)
+       for i := 0; i < len(pactVersions.Kvs); i++ {
+               pactVersion := &PactVersion{}
+               err = json.Unmarshal(pactVersions.Kvs[i].Value, pactVersion)
+               if err != nil {
+                       return nil, -1, err
+               }
+               // Obviously true, but checking it anyways
+               if pactVersion.VersionId == version.Id {
+                       pactid := pactVersion.PactId
+                       pactIds[pactid] = pactid
+               }
+       }
+       if len(pactIds) == 0 {
+               PactLogger.Errorf(nil, "pact retrieve failed, pact cannot be 
found.")
+               return &GetProviderConsumerVersionPactResponse{
+                       Response: pb.CreateResponse(scerr.ErrInternal, "pact 
cannot be found."),
+               }, -1, err
+       }
+       pactKey := util.StringJoin([]string{
+               GetBrokerPactKey(tenant),
+               strconv.Itoa(int(consumerParticipant.Id)),
+               strconv.Itoa(int(providerParticipant.Id))},
+               "/")
+       pacts, err := Store().PactVersion().Search(ctx,
+               registry.WithStrKey(pactKey),
+               registry.WithPrefix())
+
+       if err != nil {
+               return nil, -1, err
+       }
+       if len(pacts.Kvs) == 0 {
+               PactLogger.Info("[RetrieveProviderPact] No pact version found, 
sorry")
+               return nil, -1, nil
+       }
+       for i := 0; i < len(pacts.Kvs); i++ {
+               pactObj := &Pact{}
+               err = json.Unmarshal(pacts.Kvs[i].Value, pactObj)
+               if err != nil {
+                       return nil, -1, err
+               }
+               if _, ok := pactIds[pactObj.Id]; ok {
+                       //PactLogger.Infof("pact retrieve succeeded, found 
pact: %s", string(pactObj.Content))
+                       return &GetProviderConsumerVersionPactResponse{
+                               Response: 
pb.CreateResponse(pb.Response_SUCCESS, "pact found."),
+                               Pact:     pactObj.Content,
+                       }, pactObj.Id, nil
+               }
+       }
+       PactLogger.Errorf(nil, "pact retrieve failed, pact cannot be found.")
+       return &GetProviderConsumerVersionPactResponse{
+               Response: pb.CreateResponse(scerr.ErrInternal, "pact cannot be 
found."),
+       }, -1, nil
+}
+
+func DeletePactData(ctx context.Context,
+       in *BaseBrokerRequest) (*pb.Response, error) {
+       //tenant := util.ParseTenantProject(ctx)
+       allPactKey := GetBrokerRootKey() //GetBrokerVerificationKey("default") 
//util.StringJoin([]string{ apt.GetRootKey(), apt.REGISTRY_PACT_ROOT_KEY }, "/")
+
+       _, err := backend.Registry().Do(ctx,
+               registry.DEL, registry.WithStrKey(allPactKey), 
registry.WithPrefix())
+       if err != nil {
+               return pb.CreateResponse(scerr.ErrInternal, "error deleting 
pacts."), err
+       }
+       return pb.CreateResponse(pb.Response_SUCCESS, "deleting pacts 
Succeed."), nil
+}
diff --git a/server/rest/controller/rest_util.go 
b/server/rest/controller/rest_util.go
index 749900b..be626d5 100644
--- a/server/rest/controller/rest_util.go
+++ b/server/rest/controller/rest_util.go
@@ -57,3 +57,15 @@ func WriteResponse(w http.ResponseWriter, resp *pb.Response, 
obj interface{}) {
 
        WriteError(w, resp.GetCode(), resp.GetMessage())
 }
+
+func WriteBytes(w http.ResponseWriter, resp *pb.Response, json []byte) {
+       if resp.GetCode() == pb.Response_SUCCESS {
+               w.Header().Add("X-Response-Status", fmt.Sprint(http.StatusOK))
+               w.Header().Set("Content-Type", "application/json; 
charset=UTF-8")
+               w.WriteHeader(http.StatusOK)
+               w.Write(json)
+               return
+       }
+       WriteError(w, resp.GetCode(), resp.GetMessage())
+}
+

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to