Skip to content

Commit

Permalink
Merge pull request #344 from anandrgitnirman/concur
Browse files Browse the repository at this point in the history
Support the new JSON structure from Organization metadata and Service metadata
  • Loading branch information
anandrgitnirman authored Aug 2, 2019
2 parents 7c0c0fb + 9ed7373 commit f86a1c9
Show file tree
Hide file tree
Showing 22 changed files with 452 additions and 233 deletions.
55 changes: 45 additions & 10 deletions blockchain/orginzationMetadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
log "github.com/sirupsen/logrus"
"math/big"
"strings"
"time"
)

/*
Expand Down Expand Up @@ -86,8 +87,8 @@ type Group struct {

//Structure to hold the storage details of the payment
type PaymentChannelStorageClient struct {
ConnectionTimeout string `json:"connection_timeout"`
RequestTimeout string `json:"request_timeout"`
ConnectionTimeout string `json:"connection_timeout" mapstructure:"connection_timeout"`
RequestTimeout string `json:"request_timeout" mapstructure:"request_timeout"`
Endpoints []string `json:"endpoints"`
}

Expand All @@ -100,20 +101,37 @@ func InitOrganizationMetaDataFromJson(jsonData string) (metaData *OrganizationMe
return nil, err
}

//Check for mandatory validations

if err = setDerivedAttributes(metaData); err != nil {
log.WithError(err)
return nil, err
}
if err = checkMandatoryFields(metaData); err != nil {
return nil,err
}

return metaData, nil
}

func checkMandatoryFields(metaData *OrganizationMetaData) (err error ){
if metaData.daemonGroup.PaymentDetails.PaymentChannelStorageClient.Endpoints == nil {
err = fmt.Errorf("Mandatory field : ETCD Client Endpoints are mising for the Group %v ",metaData.daemonGroup.GroupName)
}
if &metaData.recipientPaymentAddress == nil {
err = fmt.Errorf("Mandatory field : Recepient Address is missing for the Group %v ",metaData.daemonGroup.GroupName)
}
return
}

func setDerivedAttributes(metaData *OrganizationMetaData) (err error) {
if metaData.daemonGroup, err = getDaemonGroup(*metaData); err != nil {
return err
}
metaData.daemonGroupID, err = ConvertBase64Encoding(metaData.daemonGroup.GroupID)
metaData.recipientPaymentAddress = common.HexToAddress(metaData.daemonGroup.PaymentDetails.PaymentAddress)
//use the checksum address ( convert the address in to a checksum address and set it back)
metaData.daemonGroup.PaymentDetails.PaymentAddress = metaData.recipientPaymentAddress.Hex()
return err
}

Expand Down Expand Up @@ -152,7 +170,7 @@ func GetOrganizationMetaDataFromIPFS(hash string) (*OrganizationMetaData, error)
return InitOrganizationMetaDataFromJson(jsondata)
}

//TODO , once the latest contract is pushed , the below method will be called

func getMetaDataURI() []byte {
//Block chain call here to get the hash of the metadata for the given Organization
reg := getRegistryCaller()
Expand All @@ -161,11 +179,9 @@ func getMetaDataURI() []byte {
organizationRegistered, err := reg.GetOrganizationById(nil, orgId)
if err != nil || !organizationRegistered.Found {
log.WithError(err).WithField("OrganizationId", config.GetString(config.OrganizationId)).
WithField("ServiceId", config.GetString(config.ServiceId)).
Panic("Error Retrieving contract details for the Given Organization and Service Ids ")
Panic("Error Retrieving contract details for the Given Organization")
}
//return organizationRegistered.metaDataURI[:] //TODO , once the latest version of the registry is published, this line will be uncommented.
return nil
return organizationRegistered.OrgMetadataURI[:]
}

//Get the Group ID the Daemon needs to associate itself to , requests belonging to a different group if will be rejected
Expand All @@ -179,8 +195,8 @@ func (metaData OrganizationMetaData) GetGroupId() [32]byte {
}

//Pass the group Name and retrieve the details of the payment address/ recipient address.
func (metaData OrganizationMetaData) GetPaymentAddress() string {
return metaData.daemonGroup.PaymentDetails.PaymentAddress
func (metaData OrganizationMetaData) GetPaymentAddress() common.Address {
return metaData.recipientPaymentAddress
}

//Payment expiration threshold
Expand All @@ -189,6 +205,25 @@ func (metaData *OrganizationMetaData) GetPaymentExpirationThreshold() *big.Int {
}

//Get the End points of the Payment Storage used to update the storage state
func (metaData OrganizationMetaData) GetPaymentStorageEndPoint() []string {
func (metaData OrganizationMetaData) GetPaymentStorageEndPoints() []string {
return metaData.daemonGroup.PaymentDetails.PaymentChannelStorageClient.Endpoints
}


//Get the connection time out defined
func (metaData OrganizationMetaData) GetConnectionTimeOut() ( connectionTimeOut time.Duration) {
connectionTimeOut, err := time.ParseDuration(metaData.daemonGroup.PaymentDetails.PaymentChannelStorageClient.ConnectionTimeout);
if err != nil {
log.Errorf(err.Error())
}
return connectionTimeOut
}

//Get the Request time out defined
func (metaData OrganizationMetaData) GetRequestTimeOut() time.Duration {
timeOut, err := time.ParseDuration(metaData.daemonGroup.PaymentDetails.PaymentChannelStorageClient.RequestTimeout);
if err != nil {
log.Errorf(err.Error())
}
return timeOut
}
9 changes: 6 additions & 3 deletions blockchain/orginzationMetadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ import (
"github.com/stretchr/testify/assert"
"math/big"
"testing"
"time"
)

var testJsonOrgGroupData = "{ \"org_name\": \"organization_name\", \"org_id\": \"org_id1\", \"groups\": [ { \"group_name\": \"default_group2\", \"group_id\": \"99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=\", \"payment\": { \"payment_address\": \"0x671276c61943A35D5F230d076bDFd91B0c47bF09\", \"payment_expiration_threshold\": 40320, \"payment_channel_storage_type\": \"etcd\", \"payment_channel_storage_client\": { \"connection_timeout\": \"5s\", \"request_timeout\": \"3s\", \"endpoints\": [ \"http://127.0.0.1:2379\" ] } } }, { \"group_name\": \"default_group\", \"group_id\": \"99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=\", \"payment\": { \"payment_address\": \"0x671276c61943A35D5F230d076bDFd91B0c47bF09\", \"payment_expiration_threshold\": 40320, \"payment_channel_storage_type\": \"etcd\", \"payment_channel_storage_client\": { \"connection_timeout\": \"5s\", \"request_timeout\": \"3s\", \"endpoints\": [ \"http://127.0.0.1:2379\" ] } } } ] }"
var testJsonOrgGroupData = "{ \"org_name\": \"organization_name\", \"org_id\": \"org_id1\", \"groups\": [ { \"group_name\": \"default_group2\", \"group_id\": \"99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=\", \"payment\": { \"payment_address\": \"0x671276c61943A35D5F230d076bDFd91B0c47bF09\", \"payment_expiration_threshold\": 40320, \"payment_channel_storage_type\": \"etcd\", \"payment_channel_storage_client\": { \"connection_timeout\": \"15s\", \"request_timeout\": \"13s\", \"endpoints\": [ \"http://127.0.0.1:2379\" ] } } }, { \"group_name\": \"default_group\", \"group_id\": \"99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=\", \"payment\": { \"payment_address\": \"0x671276c61943A35D5F230d076bDFd91B0c47bF09\", \"payment_expiration_threshold\": 40320, \"payment_channel_storage_type\": \"etcd\", \"payment_channel_storage_client\": { \"connection_timeout\": \"15s\", \"request_timeout\": \"13s\", \"endpoints\": [ \"http://127.0.0.1:2379\" ] } } } ] }"

func TestGetOrganizationMetaData(t *testing.T) {
metadata, err := InitOrganizationMetaDataFromJson(testJsonOrgGroupData)
assert.Nil(t, err)
assert.NotNil(t, metadata)
assert.Equal(t, "organization_name", metadata.OrgName)
address := metadata.GetPaymentAddress()
assert.Equal(t, "0x671276c61943A35D5F230d076bDFd91B0c47bF09", address)
assert.Equal(t, "http://127.0.0.1:2379", metadata.GetPaymentStorageEndPoint()[0])
assert.Equal(t, "0x671276c61943A35D5F230d076bDFd91B0c47bF09", address.Hex())
assert.Equal(t, "http://127.0.0.1:2379", metadata.GetPaymentStorageEndPoints()[0])
assert.Equal(t, "99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=", metadata.GetGroupIdString())
assert.Equal(t, big.NewInt(40320), metadata.GetPaymentExpirationThreshold())
grpId, _ := ConvertBase64Encoding("99ybRIg2wAx55mqVsA6sB4S7WxPQHNKqa4BPu/bhj+U=")
assert.Equal(t, grpId, metadata.GetGroupId())
assert.Equal(t, 15*time.Second, metadata.GetConnectionTimeOut())
assert.Equal(t, 13*time.Second, metadata.GetRequestTimeOut())

}

Expand Down
167 changes: 74 additions & 93 deletions blockchain/serviceMetadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,60 +20,62 @@ type ServiceMetadata struct {
DisplayName string `json:"display_name"`
Encoding string `json:"encoding"`
ServiceType string `json:"service_type"`
PaymentExpirationThreshold *big.Int `json:"payment_expiration_threshold"`
Groups []OrganizationGroup `json:"groups"`
ModelIpfsHash string `json:"model_ipfs_hash"`
MpeAddress string `json:"mpe_address"`
Pricing struct {
PriceModel string `json:"price_model"`
PackageName string `json:"package_name"`
//Price in cogs has been retained only to support backward compatibility
PriceInCogs *big.Int `json:"price_in_cogs"`
Details []struct {
ServiceName string `json:"service_name"`
MethodPricing []struct {
MethodName string `json:"method_name"`
PriceInCogs *big.Int `json:"price_in_cogs"`
} `json:"method_pricing"`
} `json:"details"`
} `json:"pricing"`
Groups []struct {
GroupName string `json:"group_name"`
GroupID string `json:"group_id"`
PaymentAddress string `json:"payment_address"`
} `json:"groups"`
Endpoints []struct {
GroupName string `json:"group_name"`
Endpoint string `json:"endpoint"`
} `json:"endpoints"`
daemonReplicaGroupIDString string
daemonReplicaGroupID [32]byte
daemonGroupName string
daemonEndPoint string
recipientPaymentAddress common.Address

multiPartyEscrowAddress common.Address
defaultPricing Pricing

defaultGroup OrganizationGroup
}

type OrganizationGroup struct {
Endpoints []string `json:"endpoints"`
GroupID string `json:"group_id"`
GroupName string `json:"group_name"`
Pricing []Pricing `json:"pricing"`
}
type Pricing struct {
PriceModel string `json:"price_model"`
PriceInCogs *big.Int `json:"price_in_cogs,omitempty"`
PackageName string `json:"package_name,omitempty"`
Default bool `json:"default,omitempty"`
PricingDetails []PricingDetails `json:"details,omitempty"`
}

type PricingDetails struct {
ServiceName string `json:"service_name"`
MethodPricing []MethodPricing `json:"method_pricing"`
}
type MethodPricing struct {
MethodName string `json:"method_name"`
PriceInCogs *big.Int `json:"price_in_cogs"`
}



func getRegistryAddressKey() common.Address {
address := config.GetRegistryAddress()
return common.HexToAddress(address)
}

func (metaData ServiceMetadata) GetDefaultPricing() Pricing {
return metaData.defaultPricing
}

func ServiceMetaData() *ServiceMetadata {
var metadata *ServiceMetadata
var err error
if config.GetBool(config.BlockchainEnabledKey) {
ipfsHash := string(getServiceMetaDataUrifromRegistry())
metadata, err = GetServiceMetaDataFromIPFS(FormatHash(ipfsHash))
} else {
//TO DO, have a snetd command to create a default metadata json file, for now just read from a local file
// when block chain reading is disabled
if metadata, err = ReadServiceMetaDataFromLocalFile("service_metadata.json"); err != nil {
fmt.Print("When Block chain is disabled it is mandatory to have a service_metadata.json file to start Daemon.Please refer to a sample file at https://github.com/singnet/snet-daemon/blob/master/service_metadata.json\n")
if err != nil {
log.WithError(err).
Panic("error on determining service metadata from file")
}
}
if err != nil {
log.WithError(err).
Panic("error on determining service metadata from file")
} else {
metadata = &ServiceMetadata{Encoding:"proto",ServiceType:"grpc"}
}
return metadata
}
Expand All @@ -85,6 +87,7 @@ func ReadServiceMetaDataFromLocalFile(filename string) (*ServiceMetadata, error)
}
strJson := string(file)
metadata, err := InitServiceMetaDataFromJson(strJson)

if err != nil {
return nil, fmt.Errorf("error reading local file service_metadata.json ")
}
Expand Down Expand Up @@ -137,76 +140,65 @@ func InitServiceMetaDataFromJson(jsonData string) (*ServiceMetadata, error) {
log.WithError(err).WithField("jsondata", jsonData)
return nil, err
}
err = setDerivedFields(metaData)

if err := setDerivedFields(metaData); err != nil {
return nil,err
}

return metaData, err
}

func setDerivedFields(metaData *ServiceMetadata) error {
err := setDaemonGroupName(metaData)
if err != nil {
return err
}
err = setDaemonGroupIDAndPaymentAddress(metaData)
if err != nil {
func setDerivedFields(metaData *ServiceMetadata) (err error) {
if err= setDefaultPricing(metaData); err != nil {
return err
}
setMultiPartyEscrowAddress(metaData)
return nil

}

func setMultiPartyEscrowAddress(metaData *ServiceMetadata) {
metaData.multiPartyEscrowAddress = common.HexToAddress(metaData.MpeAddress)

}

func setDaemonGroupName(metaData *ServiceMetadata) error {
metaData.daemonGroupName = config.GetString(config.DaemonGroupName)
//Make sure the group name specified is in the config matches to some group name in metadata
for _, endpoints := range metaData.Endpoints {
if strings.Compare(metaData.daemonGroupName, endpoints.GroupName) == 0 {
return nil
func setGroup(metaData *ServiceMetadata) (err error) {
groupName := config.GetString(config.DaemonGroupName)
for _, group := range metaData.Groups {
if strings.Compare(group.GroupName, groupName) == 0 {
metaData.defaultGroup = group
return nil
}
}
log.WithField("daemon group name does not match any of the Group Names in Metadata", metaData.daemonGroupName)
return fmt.Errorf("please set the mandatory Daemon group Name corrrectly through the config %s ", config.DaemonGroupName)
err = fmt.Errorf("group name %v in config is invalid, "+
"there was no group found with this name in the metadata", groupName)
log.WithError(err)
return err
}

func setDaemonGroupIDAndPaymentAddress(metaData *ServiceMetadata) error {
groupName := metaData.GetDaemonGroupName()

for _, group := range metaData.Groups {
if strings.Compare(groupName, group.GroupName) == 0 {
var err error
metaData.daemonReplicaGroupIDString = group.GroupID
metaData.daemonReplicaGroupID, err = ConvertBase64Encoding(group.GroupID)
if err != nil {
return err
}
metaData.recipientPaymentAddress = common.HexToAddress(group.PaymentAddress)
return nil
func setDefaultPricing(metaData *ServiceMetadata) (err error) {
if err = setGroup(metaData);err != nil {
return err
}
for _, pricing := range metaData.defaultGroup.Pricing {
if pricing.Default {
metaData.defaultPricing = pricing
return nil
}
}
log.WithField("groupName", groupName)
return fmt.Errorf("unable to determine the Daemon Group ID or the Recipient Payment Address, Daemon Group Name %s", groupName)

err = fmt.Errorf("MetaData does not have the default pricing set ")
log.WithError(err)
return err
}

func (metaData *ServiceMetadata) GetDaemonEndPoint() string {
return metaData.daemonEndPoint
func setMultiPartyEscrowAddress(metaData *ServiceMetadata) {
metaData.multiPartyEscrowAddress = common.HexToAddress(metaData.MpeAddress)
//set the checksum address ( standardized way)
metaData.MpeAddress = metaData.multiPartyEscrowAddress.Hex()

}


func (metaData *ServiceMetadata) GetMpeAddress() common.Address {
return metaData.multiPartyEscrowAddress
}

func (metaData *ServiceMetadata) GetPaymentExpirationThreshold() *big.Int {
return metaData.PaymentExpirationThreshold
}

func (metaData *ServiceMetadata) GetDaemonGroupName() string {
return metaData.daemonGroupName
}
func (metaData *ServiceMetadata) GetWireEncoding() string {
return metaData.Encoding
}
Expand All @@ -223,14 +215,3 @@ func (metaData *ServiceMetadata) GetDisplayName() string {
return metaData.DisplayName
}

func (metaData *ServiceMetadata) GetDaemonGroupID() [32]byte {
return metaData.daemonReplicaGroupID
}

func (metaData *ServiceMetadata) GetDaemonGroupIDString() string {
return metaData.daemonReplicaGroupIDString
}

func (metaData *ServiceMetadata) GetPaymentAddress() common.Address {
return metaData.recipientPaymentAddress
}
Loading

0 comments on commit f86a1c9

Please sign in to comment.