You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/02/28 02:29:58 UTC

[incubator-servicecomb-service-center] branch master updated: SC-49 Pact broker module for consumer-driven contract testing (#220)

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 <ga...@gmail.com>
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
littlecui@apache.org.