README
¶
Hyperledger Fabric chaincode kit (CCKit)
Chaincode methods router
To simplify chaincode development, we tried to compose common software development patterns, such as routing, middleware and invoke context:
-
Routing refers to determining how an application responds to a client request to a particular endpoint. Chaincode router uses rules about how to map chaincode invocation to particular handler, as well as what kind of middleware need to be used during request, for example how to convert incoming argument from []byte to target type (string, struct etc)
-
Invoke context is abstraction over ChaincodeStubInterface, represents the context of the current chaincode invocation. It holds request, response and client (Identity) reference, converted parameters, as well as state and log reference. As
Context
is an interface, it is easy to extend it with custom methods. -
Middleware functions are functions that have access to the invoke context, invoke result and the next middleware function in the chaincode’s invoke-response cycle. The next middleware function is commonly denoted by a variable named next.
Middleware
Middleware functions can perform the following tasks:
- Convert input args from byte slice to desired type
- Check access control requirements
- End the request-response cycle.
- Call the next middleware function in the stack.
Defining chaincode function and their arguments
Delegating chaincode methods handling
// Chaincode default chaincode implementation with router
type Chaincode struct {
router *Group
}
// Init initializes chain code - sets chaincode "owner"
func (cc *Chaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
// delegate handling to router
return cc.router.HandleInit(stub)
}
// Invoke - entry point for chain code invocations
func (cc *Chaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
// delegate handling to router
return cc.router.Handle(stub)
}
Chaincode function and their arguments
Example from ERC20 chaincode:
func NewErc20FixedSupply() *router.Chaincode {
r := router.New(`erc20fixedSupply`).Use(p.StrictKnown).
// Chaincode init function, initiates token smart contract with token symbol, name and totalSupply
Init(invokeInitFixedSupply, p.String(`symbol`), p.String(`name`), p.Int(`totalSupply`)).
// Get token symbol
Query(`symbol`, querySymbol).
// Get token name
Query(`name`, queryName).
// Get the total token supply
Query(`totalSupply`, queryTotalSupply).
// get account balance
Query(`balanceOf`, queryBalanceOf, p.String(`mspId`), p.String(`certId`)).
//Send value amount of tokens
Invoke(`transfer`, invokeTransfer, p.String(`toMspId`), p.String(`toCertId`), p.Int(`amount`)).
// Allow spender to withdraw from your account, multiple times, up to the _value amount.
// If this function is called again it overwrites the current allowance with _valu
Invoke(`approve`, invokeApprove, p.String(`spenderMspId`), p.String(`spenderCertId`), p.Int(`amount`)).
// Returns the amount which _spender is still allowed to withdraw from _owner]
Invoke(`allowance`, queryAllowance, p.String(`ownerMspId`), p.String(`ownerCertId`),
p.String(`spenderMspId`), p.String(`spenderCertId`)).
// Send amount of tokens from owner account to another
Invoke(`transferFrom`, invokeTransferFrom, p.String(`fromMspId`), p.String(`fromCertId`),
p.String(`toMspId`), p.String(`toCertId`), p.Int(`amount`))
return router.NewChaincode(r)
}
Documentation
¶
Overview ¶
Package router provides base router for using in chaincode Invoke function
Index ¶
- Constants
- Variables
- func EmptyContextHandler(c Context) (interface{}, error)
- type Chaincode
- type Context
- type ContextHandlerFunc
- type ContextMiddlewareFunc
- type ContextResponse
- type Group
- func (g *Group) Context(stub shim.ChaincodeStubInterface) Context
- func (g *Group) ContextHandler(path string, fn ContextHandlerFunc) *Group
- func (g *Group) Group(path string) *Group
- func (g *Group) Handle(stub shim.ChaincodeStubInterface) peer.Response
- func (g *Group) HandleContext(c Context) peer.Response
- func (g *Group) HandleInit(stub shim.ChaincodeStubInterface) peer.Response
- func (g *Group) Init(handler HandlerFunc, middleware ...MiddlewareFunc) *Group
- func (g *Group) Invoke(path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Group
- func (g *Group) Pre(middleware ...ContextMiddlewareFunc) *Group
- func (g *Group) Query(path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Group
- func (g *Group) StubHandler(path string, fn StubHandlerFunc) *Group
- func (g *Group) Use(middleware ...MiddlewareFunc) *Group
- type HandlerFunc
- type InterfaceMap
- type MiddlewareFunc
- type Response
- type StubHandlerFunc
Constants ¶
const InitFunc = `init`
Variables ¶
var ( // ErrEmptyArgs occurs when trying to invoke chaincode method with empty args ErrEmptyArgs = errors.New(`empty args`) // ErrMethodNotFound occurs when trying to invoke non existent chaincode method ErrMethodNotFound = errors.New(`chaincode method not found`) // ErrArgsNumMismatch occurs when the number of declared and the number of arguments passed does not match ErrArgsNumMismatch = errors.New(`chaincode method args count mismatch`) // ErrHandlerError error in handler ErrHandlerError = errors.New(`router handler error`) )
Functions ¶
func EmptyContextHandler ¶
Types ¶
type Chaincode ¶
type Chaincode struct {
// contains filtered or unexported fields
}
Chaincode default chaincode implementation with router
func NewChaincode ¶
NewChaincode new default chaincode implementation
type Context ¶
type Context interface { Stub() shim.ChaincodeStubInterface Client() (cid.ClientIdentity, error) Response() Response Logger() *shim.ChaincodeLogger Path() string State() state.State Time() (time.Time, error) ReplaceArgs(args [][]byte) Context // replace args, for usage in preMiddleware GetArgs() [][]byte // to remove, be only get/set Args() InterfaceMap Arg(string) interface{} ArgString(string) string ArgBytes(string) []byte ArgInt(string) int SetArg(string, interface{}) Get(string) interface{} Set(string, interface{}) SetEvent(string, interface{}) error }
Context of chaincode invoke
type ContextHandlerFunc ¶
ContextHandlerFunc use stub context as input parameter
type ContextMiddlewareFunc ¶
type ContextMiddlewareFunc func(ContextHandlerFunc, ...int) ContextHandlerFunc
ContextMiddlewareFunc middleware for ContextHandlerFun
type ContextResponse ¶
type ContextResponse struct {
// contains filtered or unexported fields
}
ContextResponse implementation
func (ContextResponse) Create ¶
func (c ContextResponse) Create(data interface{}, err interface{}) peer.Response
Create returns error response if err != nil
func (ContextResponse) Error ¶
func (c ContextResponse) Error(err interface{}) peer.Response
Error response
func (ContextResponse) Success ¶
func (c ContextResponse) Success(data interface{}) peer.Response
Success response
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group of chain code functions
func (*Group) Context ¶
func (g *Group) Context(stub shim.ChaincodeStubInterface) Context
Context returns chain code invoke context for provided path and stub
func (*Group) ContextHandler ¶
func (g *Group) ContextHandler(path string, fn ContextHandlerFunc) *Group
ContextHandler adds new context handler using presented path
func (*Group) Group ¶
Group gets new group using presented path New group can be used as independent
func (*Group) Handle ¶
func (g *Group) Handle(stub shim.ChaincodeStubInterface) peer.Response
Handle used for using in CC Invoke function Must be called after adding new routes using Add function
func (*Group) HandleInit ¶
func (g *Group) HandleInit(stub shim.ChaincodeStubInterface) peer.Response
HandleInit handle chaincode init method
func (*Group) Init ¶
func (g *Group) Init(handler HandlerFunc, middleware ...MiddlewareFunc) *Group
func (*Group) Invoke ¶
func (g *Group) Invoke(path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Group
Invoke configure handler and middleware functions for chain code function name
func (*Group) Pre ¶
func (g *Group) Pre(middleware ...ContextMiddlewareFunc) *Group
func (*Group) Query ¶
func (g *Group) Query(path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Group
Query alias for invoke
func (*Group) StubHandler ¶
func (g *Group) StubHandler(path string, fn StubHandlerFunc) *Group
StubHandler adds new stub handler using presented path
func (*Group) Use ¶
func (g *Group) Use(middleware ...MiddlewareFunc) *Group
Use middleware function in chain code functions group
type HandlerFunc ¶
HandlerFunc returns result as interface and error, this is converted to peer.Response via response.Create
type MiddlewareFunc ¶
type MiddlewareFunc func(HandlerFunc, ...int) HandlerFunc
MiddlewareFunc middleware for HandlerFunc
type Response ¶
type Response interface { Error(err interface{}) peer.Response Success(data interface{}) peer.Response Create(data interface{}, err interface{}) peer.Response }
Response chaincode interface
type StubHandlerFunc ¶
type StubHandlerFunc func(shim.ChaincodeStubInterface) peer.Response
StubHandlerFunc acts as raw chaincode invoke method, accepts stub and returns peer.Response