-
Notifications
You must be signed in to change notification settings - Fork 12
Commons
The purpose of the commons package is to contain files that are used throughout the components in the platform.
Packages provides a high-level package description of each package with a link to the godocs for the individual packages.
The properties are loaded into a structure that is accessible throughout the system. The loading to the properties structure is done through json serialization into the object. :
type Config struct {
HttpEndpoint *Endpoint `json:"httpEndpoint"`
GrpcEndpoint *Endpoint `json:"grpcEndpoint"`
GrpcTimeout int `json:"grpcTimeout"`
SeedEndpoints []*Endpoint `json:"seedEndpoints"`
DelegateEndpoints []*Endpoint `json:"delegateEndpoints"`
UseQuantumEntropy bool `json:"useQuantumEntropy"`
GenesisTransaction string `json:"genesisTransaction"`
}
A Sample json is as follows:
{
"httpEndpoint":{"host":"0.0.0.0","port":1975},
"grpcEndpoint":{"host":"127.0.0.1","port":1973},
"grpcTimeout":5,
"seedEndpoints":[{"host":"127.0.0.1","port":1973}],
"delegateEndpoints":[],
"useQuantumEntropy":false,
"genesisTransaction":"{\"hash\":\"a48ff2bd1fb99d9170e2bae2f4ed94ed79dbc8c1002986f8054a369655e29276\",\"type\":0,\"from\":\"e6098cc0d5c20c6c31c4d69f0201a02975264e94\",\"to\":\"3ed25f42484d517cdfc72cafb7ebc9e8baa52c2c\",\"value\":10000000,\"data\":\"\",\"time\":0,\"signature\":\"03c1fdb91cd10aa441e0025dd21def5ebe045762c1eeea0f6a3f7e63b27deb9c40e08b656a744f6c69c55f7cb41751eebd49c1eedfbd10b861834f0352c510b200\",\"hertz\":0,\"fromName\":\"\",\"toName\":\"\"}"}
}
The system will generate a account file in JSON format. The first time Disgo is started on a new machine, the account.json is generated automatically. This file is stored in the users disgo/config/account.json like the following:
{
"address":"aa23bd89e23f826cf24afc73caad5ee72905b0c5",
"balance":0,
"created":"0001-01-01T00:00:00Z",
"name":"",
"nonce":0,
"privateKey":"d05b2e5111ee756a7bc9a8a7c5b9c5e561bf913c35971aa0258abd1198a99883",
"updated":"0001-01-01T00:00:00Z"
}
In the types package, we have a common interface IService
. This interface is implemented by all services that run in a waitgroup and listen for requests. By implementing this interface, these services can be started in a generic way by some client code.
The IService requires to functions:
IsRunning() bool
- which returns the run state of the service
Go(waitGroup *sync.WaitGroup)
- which starts that service and waits for requests
A client should declare something with an array of IService, which can be added to and then use a simple loop to call the common Go function on it.
type Server struct {
services []types.IService
}
Add all of the different services that are desired. In this example I'm using GRPC. Of note, we want the disgo_commons grpc_service to be started last so that the other services are all registered prior. (Will revisit this)
server.services = append(server.services, package.NewServiceThatUsesGPRC())
server.services = append(server.services, package.AnotherNewServiceThatUsesGPRC())
server.services = append(server.services, services.NewGrpcService())
We want to have all of the services in a WaitGroup listening for incoming messages.
// Run services.
var waitGroup sync.WaitGroup
for _, service := range server.services {
log.WithFields(log.Fields{
"method": "Server.Go",
}).Info("starting " + service.Name() + "...")
go service.Go(&waitGroup)
waitGroup.Add(1)
}
waitGroup.Wait()
After this loop, all desired services are registered and listening. The last to start is the grpc_service which sets up the listener, registers everything with GRPC and starts serving requests: Here is the Go() function for grpc_service:
func (grpcService *GrpcService) Go(waitGroup *sync.WaitGroup) {
grpcService.running = true
listener, error := net.Listen("tcp", ":"+strconv.Itoa(grpcService.Port))
if error != nil {
log.Fatalf("failed to listen: %v", error)
}
// Serve.
log.WithFields(log.Fields{
"method": grpcService.Name() + ".Go",
}).Info("listening on " + strconv.Itoa(grpcService.Port))
reflection.Register(GetGrpcServer())
if error := GetGrpcServer().Serve(listener); error != nil {
log.Fatalf("failed to serve: %v", error)
grpcService.running = false
}
}
The config package contains the Properties structure that defines the system properties used by the system to initialize communication, set the state for some objects.
see the godoc for details of the implementation
constants contains static values that are used by multiple components of the system. Hard coded values should be avoided and this package supports this philosopy.
see the godoc for details of the implementation
The crypto package is borrowed from our friends at Ethereum. It has the c libraries and useful implementation we needed for the project.
see the godoc for details of the implementation
The math package is also borrowed from our friends at Ethereum to support the crypto package.
see the godoc for details of the implementation
The services package contains the implementation of common services used in multiple components. At the moment we have two common services, both of which support transport protocols: GRCP, HTTP.
The approach to designing these services is to provide a singleton instance that can be accessed from any file in the system. This allows for other services to use the common transport service to register itself.
For example: the GRPC Service singleton is an argument in the registration portion for other services that want to communicate over GRPC. The registration function is a generated function from protobuf.
In disgover, GetGrpcServer() is used as follows:
// RegisterGrpc - Registers the transport layer as GRPC
// uses the commons/grpc_service
func (disGoverService *DisGoverService) RegisterGrpc() *DisGoverService {
proto.RegisterDisgoverRPCServer(services.GetGrpcServer(), disGoverService)
return disGoverService
}
The goal is to make it simple to register.
see the godoc for details of the implementation
types contains structures and interfaces that are common to the system. These are files that already do or would likely cause circular dependencies.
see the godoc for details of the implementation
utils is meant for common utility functions. Something most of us end up needing in every project we develop on.