grpc

package
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2024 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package grpc provides a GRPC-based router for smart contract method invocation. This package uses protocol buffers (protobuf) and GRPC service descriptions to dynamically route and invoke smart contract methods based on predefined service and method definitions.

GRPC Routing

The core functionality of this package revolves around the Router type, which implements the github.com/anoideaopen/foundation/core/routing.Router interface. The router dynamically routes incoming method calls based on GRPC service definitions and protobuf method options.

Supported GRPC Method Types:

  • Transaction: Methods that modify the blockchain state. These are identified by the custom `method_type` option set to `METHOD_TYPE_TRANSACTION` in the protobuf definition.
  • Invoke: Methods that are executed directly as Hyperledger Fabric Invoke transactions, bypassing the batching mechanism.
  • Query: Read-only methods that retrieve data without altering the blockchain state.

The router also supports custom method authorization settings, defined using the `method_auth` option in the protobuf file. These settings allow developers to specify whether a method requires authentication.

Protobuf Example

Here is an example of a protobuf definition that includes custom extensions for method types and authorization:

syntax = "proto3";

package foundationtoken;

option go_package = "github.com/anoideaopen/foundation/test/chaincode/fiat/service";

import "google/protobuf/empty.proto";
import "validate/validate.proto";
import "method_options.proto"; // Import custom options.

message Address {
    string base58check = 1 [(validate.rules).string = {pattern: "^[1-9A-HJ-NP-Za-km-z]+$"}];
}

message BigInt {
    string value = 1 [(validate.rules).string = {pattern: "^[0-9]+$"}];
}

message BalanceAdjustmentRequest {
    Address address = 1 [(validate.rules).message.required = true];
    BigInt amount   = 2 [(validate.rules).message.required = true];
    string reason   = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
}

service FiatService {
    rpc AddBalanceByAdmin(BalanceAdjustmentRequest) returns (google.protobuf.Empty) {
        option (foundation.method_type) = METHOD_TYPE_TRANSACTION;
    }
}

Usage Example

To use the GRPC router in your chaincode, you can define a service in your Go code that implements the methods defined in your protobuf file, and then register this service with the GRPC router:

package main

import (
    "context"
    "errors"
    mbig "math/big"

    "github.com/anoideaopen/foundation/core/routing/grpc"
    "github.com/anoideaopen/foundation/test/chaincode/fiat/service"
    "google.golang.org/protobuf/types/known/emptypb"
)

// FiatToken represents a custom smart contract
type FiatToken struct {
    service.UnimplementedFiatServiceServer
}

// AddBalanceByAdmin implements a method to add balance by an admin
func (ft *FiatToken) AddBalanceByAdmin(ctx context.Context, req *service.BalanceAdjustmentRequest) (*emptypb.Empty, error) {
    if grpc.SenderFromContext(ctx) == "" {
        return nil, errors.New("unauthorized")
    }

    if grpc.StubFromContext(ctx) == nil {
        return nil, errors.New("stub is nil")
    }

    value, _ := mbig.NewInt(0).SetString(req.GetAmount().GetValue(), 10)
    return &emptypb.Empty{}, balance.Add(
        grpc.StubFromContext(ctx),
        balance.BalanceTypeToken,
        req.GetAddress().GetBase58Check(),
        "",
        value,
    )
}

func main() {
    contract := &FiatToken{}
    grpcRouter := grpc.NewRouter()

    // Register the service with the GRPC router
    service.RegisterFiatServiceServer(grpcRouter, contract)

    // Initialize chaincode with the GRPC router
    cc, err := core.NewCC(
        contract,
        core.WithRouters(grpcRouter),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Start chaincode
    if err = cc.Start(); err != nil {
        log.Fatal(err)
    }
}

Method Invocation and Authorization

When a method is invoked via the GRPC router, the router first checks the method options defined in the protobuf file to determine the type of method (transaction, invoke, or query) and whether authentication is required. If authentication is required, the router will validate the sender before invoking the method.

Below is an example of initializing a GRPC router alongside a reflection-based router:

See: github.com/anoideaopen/foundation/test/chaincode/fiat

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnsupportedMethod        = errors.New("unsupported method")
	ErrInvalidNumberOfArguments = errors.New("invalid number of arguments")
	ErrInterfaceNotProtoMessage = errors.New("interface is not a proto.Message")
)

Routing errors.

Functions

func ContextWithSender

func ContextWithSender(parent context.Context, sender string) context.Context

ContextWithSender adds a sender to the context.

func ContextWithStub

func ContextWithStub(parent context.Context, stub shim.ChaincodeStubInterface) context.Context

ContextWithStub adds a stub to the context.

func FindServiceDescriptor

func FindServiceDescriptor(serviceName string) protoreflect.ServiceDescriptor

FindServiceDescriptor finds the service descriptor by the given service name.

func FullNameToURL

func FullNameToURL(fullMethodName string) string

FullNameToURL transforms a method name from "package.Service.Method" to "/package.Service/Method"

func SenderFromContext

func SenderFromContext(parent context.Context) string

SenderFromContext retrieves a sender from the context.

func StubFromContext

func StubFromContext(parent context.Context) shim.ChaincodeStubInterface

StubFromContext retrieves a stub from the context.

func URLToServiceAndMethod added in v0.0.4

func URLToServiceAndMethod(url string) (string, string)

URLToServiceAndMethod extracts the service name and method name from a URL.

Types

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router routes method calls to contract methods based on gRPC service description.

func NewRouter

func NewRouter() *Router

NewRouter creates a new grpc.Router instance.

func (*Router) ArgCount added in v0.0.4

func (r *Router) ArgCount(method string) int

ArgCount returns the number of arguments the method takes (excluding the receiver).

func (*Router) AuthRequired added in v0.0.4

func (r *Router) AuthRequired(method string) bool

AuthRequired indicates if the method requires authentication.

func (*Router) Check

func (r *Router) Check(stub shim.ChaincodeStubInterface, method string, args ...string) error

Check validates the provided arguments for the specified method.

func (*Router) Function added in v0.0.4

func (r *Router) Function(method string) (function string)

Function returns the name of the chaincode function by the specified method.

func (*Router) Handlers added in v0.0.4

func (r *Router) Handlers() map[string]string

Handlers returns a map of method names to chaincode functions.

func (*Router) Invoke

func (r *Router) Invoke(stub shim.ChaincodeStubInterface, method string, args ...string) ([]byte, error)

Invoke calls the specified method with the provided arguments.

func (*Router) IsInvoke added in v0.0.4

func (r *Router) IsInvoke(method string) bool

IsInvoke checks if the method is an invoke type.

func (*Router) IsQuery added in v0.0.4

func (r *Router) IsQuery(method string) bool

IsQuery checks if the method is a query type.

func (*Router) IsTransaction added in v0.0.4

func (r *Router) IsTransaction(method string) bool

IsTransaction checks if the method is a transaction type.

func (*Router) Method added in v0.0.4

func (r *Router) Method(function string) (method string)

Method retrieves the method associated with the specified chaincode function.

func (*Router) RegisterService

func (r *Router) RegisterService(desc *grpc.ServiceDesc, impl any)

RegisterService registers a service and its implementation to the concrete type implementing this interface. It may not be called once the server has started serving. desc describes the service and its methods and handlers. impl is the service implementation which is passed to the method handlers.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL