Commit 82778b85 authored by hxzqlh's avatar hxzqlh Committed by 33cn

add 'echo' executor

parent c9bb4693
package commands
import (
"encoding/json"
"fmt"
"os"
"github.com/33cn/chain33/rpc/jsonclient"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
"github.com/spf13/cobra"
)
// 本执行器的命令行初始化总入口
func EchoCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "echo",
Short: "echo commandline interface",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
QueryCmd(), // 查询消息记录
// 如果有其它命令,在这里加入
)
return cmd
}
func QueryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Short: "query message history",
Run: queryMesage,
}
addPingPangFlags(cmd)
return cmd
}
func addPingPangFlags(cmd *cobra.Command) {
// type参数,指定查询的消息类型,为uint32类型,默认值为1,通过-t参数指定
cmd.Flags().Uint32P("type", "t", 1, "message type, 1:ping 2:pang")
//cmd.MarkFlagRequired("type")
// message参数,执行消息内容,为string类型,默认值为空,通过-m参数制定
cmd.Flags().StringP("message", "m", "", "message content")
cmd.MarkFlagRequired("message")
}
func queryMesage(cmd *cobra.Command, args []string) {
// 这个是命令行的默认参数,可以制定调用哪一个服务地址
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
echoType, _ := cmd.Flags().GetUint32("type")
msg, _ := cmd.Flags().GetString("message")
// 创建RPC客户端,调用我们实现的QueryPing服务接口
client, err := jsonclient.NewJSONClient(rpcLaddr)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
// 初始化查询参数结构
var action = &echotypes.Query{Msg: msg}
if echoType != 1 {
fmt.Fprintln(os.Stderr, "not support")
return
}
var result echotypes.QueryResult
err = client.Call("echo.QueryPing", action, &result)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
data, err := json.MarshalIndent(result, "", " ")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(string(data))
}
package doc
// An easy to learn executor example references:
// 1. https://chain.33.cn/document/79#4%20%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91
// 2. https://chain.33.cn/document/82
package executor
import "github.com/33cn/chain33/types"
// 本执行器不做任何校验
func (h *Echo) CheckTx(tx *types.Transaction, index int) error {
return nil
}
\ No newline at end of file
package executor
import (
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
var (
// 执行交易生成的数据KEY
KeyPrefixPing = "mavl-echo-ping:%s"
KeyPrefixPang = "mavl-echo-pang:%s"
// 本地执行生成的数据KEY
KeyPrefixPingLocal = "LODB-echo-ping:%s"
KeyPrefixPangLocal = "LODB-echo-pang:%s"
)
// 初始化时通过反射获取本执行器的方法列表
func init() {
ety := types.LoadExecutorType(echotypes.EchoX)
ety.InitFuncList(types.ListMethod(&Echo{}))
}
//本执行器的初始化动作,向系统注册本执行器,这里生效高度暂写为0
func Init(name string, sub []byte) {
dapp.Register(echotypes.EchoX, newEcho, 0)
}
// 定义执行器对象
type Echo struct {
dapp.DriverBase
}
// 执行器对象初始化包装逻辑,后面的两步设置子对象和设置执行器类型必不可少
func newEcho() dapp.Driver {
c := &Echo{}
c.SetChild(c)
c.SetExecutorType(types.LoadExecutorType(echotypes.EchoX))
return c
}
// 返回本执行器驱动名称
func (h *Echo) GetDriverName() string {
return echotypes.EchoX
}
package executor
import (
"fmt"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
func (h *Echo) Exec_Ping(ping *echotypes.Ping, tx *types.Transaction, index int) (*types.Receipt, error) {
msg := ping.Msg
res := fmt.Sprintf("%s, ping ping ping!", msg)
xx := &echotypes.PingLog{Msg: msg, Echo: res}
logs := []*types.ReceiptLog{{Ty: echotypes.TyLogPing, Log: types.Encode(xx)}}
kv := []*types.KeyValue{{Key: []byte(fmt.Sprintf(KeyPrefixPing, msg)), Value: []byte(res)}}
receipt := &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}
return receipt, nil
}
func (h *Echo) Exec_Pang(ping *echotypes.Pang, tx *types.Transaction, index int) (*types.Receipt, error) {
msg := ping.Msg
res := fmt.Sprintf("%s, pang pang pang!", msg)
xx := &echotypes.PangLog{Msg: msg, Echo: res}
logs := []*types.ReceiptLog{{Ty: echotypes.TyLogPang, Log: types.Encode(xx)}}
kv := []*types.KeyValue{{Key: []byte(fmt.Sprintf(KeyPrefixPang, msg)), Value: []byte(res)}}
receipt := &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}
return receipt, nil
}
package executor
import (
"fmt"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// 交易执行成功,将本消息对应的数值减1
func (h *Echo) ExecDelLocal_Ping(ping *echotypes.Ping, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
// 这里简化处理,不做基本的零值及错误检查了
var pingLog echotypes.PingLog
types.Decode(receipt.Logs[0].Log, &pingLog)
localKey := []byte(fmt.Sprintf(KeyPrefixPingLocal, pingLog.Msg))
oldValue, err := h.GetLocalDB().Get(localKey)
if err != nil {
return nil, err
}
types.Decode(oldValue, &pingLog)
if pingLog.Count > 0 {
pingLog.Count -= 1
}
val := types.Encode(&pingLog)
if pingLog.Count == 0 {
val = nil
}
kv := []*types.KeyValue{{Key: localKey, Value: val}}
return &types.LocalDBSet{KV: kv}, nil
}
// 交易执行成功,将本消息对应的数值减1
func (h *Echo) ExecDelLocal_Pang(ping *echotypes.Pang, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
// 这里简化处理,不做基本的零值及错误检查了
var pangLog echotypes.PangLog
types.Decode(receipt.Logs[0].Log, &pangLog)
localKey := []byte(fmt.Sprintf(KeyPrefixPangLocal, pangLog.Msg))
oldValue, err := h.GetLocalDB().Get(localKey)
if err != nil {
return nil, err
}
types.Decode(oldValue, &pangLog)
if pangLog.Count > 0 {
pangLog.Count -= 1
}
val := types.Encode(&pangLog)
if pangLog.Count == 0 {
val = nil
}
kv := []*types.KeyValue{{Key: localKey, Value: val}}
return &types.LocalDBSet{KV: kv}, nil
}
package executor
import (
"fmt"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// 交易执行成功,将本消息对应的数值加1
func (h *Echo) ExecLocal_Ping(ping *echotypes.Ping, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
// 这里简化处理,不做基本的零值及错误检查了
var pingLog echotypes.PingLog
types.Decode(receipt.Logs[0].Log, &pingLog)
localKey := []byte(fmt.Sprintf(KeyPrefixPingLocal, pingLog.Msg))
oldValue, err := h.GetLocalDB().Get(localKey)
if err != nil && err != types.ErrNotFound {
return nil, err
}
if err == nil {
types.Decode(oldValue, &pingLog)
}
pingLog.Count += 1
kv := []*types.KeyValue{{Key: localKey, Value: types.Encode(&pingLog)}}
return &types.LocalDBSet{KV: kv}, nil
}
// 交易执行成功,将本消息对应的数值加1
func (h *Echo) ExecLocal_Pang(ping *echotypes.Pang, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
// 这里简化处理,不做基本的零值及错误检查了
var pangLog echotypes.PangLog
types.Decode(receipt.Logs[0].Log, &pangLog)
localKey := []byte(fmt.Sprintf(KeyPrefixPangLocal, pangLog.Msg))
oldValue, err := h.GetLocalDB().Get(localKey)
if err != nil && err != types.ErrNotFound {
return nil, err
}
if err == nil {
types.Decode(oldValue, &pangLog)
}
pangLog.Count += 1
kv := []*types.KeyValue{{Key: localKey, Value: types.Encode(&pangLog)}}
return &types.LocalDBSet{KV: kv}, nil
}
package executor
import (
"fmt"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
func (h *Echo) Query_GetPing(in *echotypes.Query) (types.Message, error) {
var pingLog echotypes.PingLog
localKey := []byte(fmt.Sprintf(KeyPrefixPingLocal, in.Msg))
value, err := h.GetLocalDB().Get(localKey)
if err != nil {
return nil, err
}
types.Decode(value, &pingLog)
res := echotypes.QueryResult{Msg: in.Msg, Count: pingLog.Count}
return &res, nil
}
func (h *Echo) Query_GetPang(in *echotypes.Query) (types.Message, error) {
var pangLog echotypes.PangLog
localKey := []byte(fmt.Sprintf(KeyPrefixPangLocal, in.Msg))
value, err := h.GetLocalDB().Get(localKey)
if err != nil {
return nil, err
}
types.Decode(value, &pangLog)
res := echotypes.QueryResult{Msg: in.Msg, Count: pangLog.Count}
return &res, nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package echo
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/echo/commands"
"github.com/33cn/plugin/plugin/dapp/echo/executor"
"github.com/33cn/plugin/plugin/dapp/echo/rpc"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: echotypes.EchoX,
ExecName: echotypes.EchoX,
Exec: executor.Init,
Cmd: commands.EchoCmd,
RPC: rpc.Init,
})
}
syntax = "proto3";
package echo;
// ping操作action
message Ping {
string msg = 1;
}
// pang操作action
message Pang {
string msg = 1;
}
// 本执行器的统一Action结构
message EchoAction {
oneof value {
Ping ping = 1;
Pang pang = 2;
}
int32 ty = 3;
}
// ping操作生成的日志结构
message PingLog {
string msg = 1;
string echo = 2;
int32 count = 3;
}
// pang操作生成的日志结构
message PangLog {
string msg = 1;
string echo = 2;
int32 count = 3;
}
// 查询请求结构
message Query {
string msg = 1;
}
// 查询结果结构
message QueryResult {
string msg = 1;
int32 count = 2;
}
\ No newline at end of file
package rpc
import (
"context"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
echotypes "github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// 对外提供服务的RPC接口总体定义
type Jrpc struct {
cli *channelClient
}
// RPC接口的本地实现
type channelClient struct {
rpctypes.ChannelClient
}
func Init(name string, s rpctypes.RPCServer) {
cli := &channelClient{}
// 为了简单起见,这里只注册Jrpc,如果提供grpc的话也在这里注册
cli.Init(name, s, &Jrpc{cli: cli}, nil)
}
// 本合约的查询操作可以使用通用的Query接口,这里单独封装rpc的Query接口只是为了说明实现方式
// 接收客户端请求,并调用本地具体实现逻辑,然后返回结果
func (c *Jrpc) QueryPing(param *echotypes.Query, result *interface{}) error {
if param == nil {
return types.ErrInvalidParam
}
// 将具体的接口实现传递给本地逻辑
reply, err := c.cli.QueryPing(context.Background(), param)
if err != nil {
return err
}
*result = reply
return nil
}
// 本地具体实现逻辑
func (c *channelClient) QueryPing(ctx context.Context, queryParam *echotypes.Query) (types.Message, error) {
return c.Query(echotypes.EchoX, "GetPing", queryParam)
}
package echo
import (
"encoding/json"
"math/rand"
"strings"
"time"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
)
func (e EchoType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
elog.Debug("echo.CreateTx", "action", action)
// 只接受ping/pang两种交易操作
if action == "ping" || action == "pang" {
var param EchoTx
err := json.Unmarshal(message, &param)
if err != nil {
elog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam
}
return createPingTx(action, &param)
} else {
return nil, types.ErrNotSupport
}
}
func createPingTx(op string, parm *EchoTx) (*types.Transaction, error) {
var action *EchoAction
var err error
if strings.EqualFold(op, "ping") {
action, err = getPingAction(parm)
} else {
action, err = getPangAction(parm)
}
if err != nil {
return nil, err
}
tx := &types.Transaction{
Execer: []byte(types.ExecName(EchoX)),
Payload: types.Encode(action),
Nonce: rand.New(rand.NewSource(time.Now().UnixNano())).Int63(),
To: address.ExecAddress(types.ExecName(EchoX)),
}
return tx, nil
}
func getPingAction(parm *EchoTx) (*EchoAction, error) {
pingAction := &Ping{Msg: parm.Message}
action := &EchoAction{
Value: &EchoAction_Ping{Ping: pingAction},
Ty: ActionPing,
}
return action, nil
}
func getPangAction(parm *EchoTx) (*EchoAction, error) {
pangAction := &Pang{Msg: parm.Message}
action := &EchoAction{
Value: &EchoAction_Pang{Pang: pangAction},
Ty: ActionPang,
}
return action, nil
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: echo.proto
/*
Package echo is a generated protocol buffer package.
It is generated from these files:
echo.proto
It has these top-level messages:
Ping
Pang
EchoAction
PingLog
PangLog
Query
QueryResult
*/
package echo
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// 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
// ping操作action
type Ping struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
}
func (m *Ping) Reset() { *m = Ping{} }
func (m *Ping) String() string { return proto.CompactTextString(m) }
func (*Ping) ProtoMessage() {}
func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Ping) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
// pang操作action
type Pang struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
}
func (m *Pang) Reset() { *m = Pang{} }
func (m *Pang) String() string { return proto.CompactTextString(m) }
func (*Pang) ProtoMessage() {}
func (*Pang) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Pang) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
// 本执行器的统一Action结构
type EchoAction struct {
// Types that are valid to be assigned to Value:
// *EchoAction_Ping
// *EchoAction_Pang
Value isEchoAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,3,opt,name=ty" json:"ty,omitempty"`
}
func (m *EchoAction) Reset() { *m = EchoAction{} }
func (m *EchoAction) String() string { return proto.CompactTextString(m) }
func (*EchoAction) ProtoMessage() {}
func (*EchoAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type isEchoAction_Value interface {
isEchoAction_Value()
}
type EchoAction_Ping struct {
Ping *Ping `protobuf:"bytes,1,opt,name=ping,oneof"`
}
type EchoAction_Pang struct {
Pang *Pang `protobuf:"bytes,2,opt,name=pang,oneof"`
}
func (*EchoAction_Ping) isEchoAction_Value() {}
func (*EchoAction_Pang) isEchoAction_Value() {}
func (m *EchoAction) GetValue() isEchoAction_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *EchoAction) GetPing() *Ping {
if x, ok := m.GetValue().(*EchoAction_Ping); ok {
return x.Ping
}
return nil
}
func (m *EchoAction) GetPang() *Pang {
if x, ok := m.GetValue().(*EchoAction_Pang); ok {
return x.Pang
}
return nil
}
func (m *EchoAction) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*EchoAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _EchoAction_OneofMarshaler, _EchoAction_OneofUnmarshaler, _EchoAction_OneofSizer, []interface{}{
(*EchoAction_Ping)(nil),
(*EchoAction_Pang)(nil),
}
}
func _EchoAction_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*EchoAction)
// value
switch x := m.Value.(type) {
case *EchoAction_Ping:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Ping); err != nil {
return err
}
case *EchoAction_Pang:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Pang); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("EchoAction.Value has unexpected type %T", x)
}
return nil
}
func _EchoAction_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*EchoAction)
switch tag {
case 1: // value.ping
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(Ping)
err := b.DecodeMessage(msg)
m.Value = &EchoAction_Ping{msg}
return true, err
case 2: // value.pang
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(Pang)
err := b.DecodeMessage(msg)
m.Value = &EchoAction_Pang{msg}
return true, err
default:
return false, nil
}
}
func _EchoAction_OneofSizer(msg proto.Message) (n int) {
m := msg.(*EchoAction)
// value
switch x := m.Value.(type) {
case *EchoAction_Ping:
s := proto.Size(x.Ping)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *EchoAction_Pang:
s := proto.Size(x.Pang)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// ping操作生成的日志结构
type PingLog struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
Echo string `protobuf:"bytes,2,opt,name=echo" json:"echo,omitempty"`
Count int32 `protobuf:"varint,3,opt,name=count" json:"count,omitempty"`
}
func (m *PingLog) Reset() { *m = PingLog{} }
func (m *PingLog) String() string { return proto.CompactTextString(m) }
func (*PingLog) ProtoMessage() {}
func (*PingLog) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *PingLog) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
func (m *PingLog) GetEcho() string {
if m != nil {
return m.Echo
}
return ""
}
func (m *PingLog) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
// pang操作生成的日志结构
type PangLog struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
Echo string `protobuf:"bytes,2,opt,name=echo" json:"echo,omitempty"`
Count int32 `protobuf:"varint,3,opt,name=count" json:"count,omitempty"`
}
func (m *PangLog) Reset() { *m = PangLog{} }
func (m *PangLog) String() string { return proto.CompactTextString(m) }
func (*PangLog) ProtoMessage() {}
func (*PangLog) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *PangLog) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
func (m *PangLog) GetEcho() string {
if m != nil {
return m.Echo
}
return ""
}
func (m *PangLog) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
// 查询请求结构
type Query struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
}
func (m *Query) Reset() { *m = Query{} }
func (m *Query) String() string { return proto.CompactTextString(m) }
func (*Query) ProtoMessage() {}
func (*Query) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *Query) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
// 查询结果结构
type QueryResult struct {
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
Count int32 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"`
}
func (m *QueryResult) Reset() { *m = QueryResult{} }
func (m *QueryResult) String() string { return proto.CompactTextString(m) }
func (*QueryResult) ProtoMessage() {}
func (*QueryResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *QueryResult) GetMsg() string {
if m != nil {
return m.Msg
}
return ""
}
func (m *QueryResult) GetCount() int32 {
if m != nil {
return m.Count
}
return 0
}
func init() {
proto.RegisterType((*Ping)(nil), "echo.Ping")
proto.RegisterType((*Pang)(nil), "echo.Pang")
proto.RegisterType((*EchoAction)(nil), "echo.EchoAction")
proto.RegisterType((*PingLog)(nil), "echo.PingLog")
proto.RegisterType((*PangLog)(nil), "echo.PangLog")
proto.RegisterType((*Query)(nil), "echo.Query")
proto.RegisterType((*QueryResult)(nil), "echo.QueryResult")
}
func init() { proto.RegisterFile("echo.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 215 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x91, 0x31, 0x4b, 0xc7, 0x30,
0x10, 0xc5, 0x6d, 0xda, 0x58, 0x7a, 0x05, 0x91, 0xe0, 0x10, 0xb7, 0xd2, 0xa9, 0x53, 0x07, 0xc5,
0x0f, 0xa0, 0x50, 0x70, 0x70, 0xd0, 0x7c, 0x83, 0x18, 0x42, 0x1b, 0xa8, 0x49, 0x69, 0x13, 0xa1,
0xdf, 0x5e, 0x72, 0x2d, 0xa2, 0x90, 0xed, 0xbf, 0xbd, 0xf0, 0x1e, 0xbf, 0x97, 0xbb, 0x03, 0xd0,
0x6a, 0x72, 0xfd, 0xb2, 0x3a, 0xef, 0x58, 0x11, 0x75, 0xcb, 0xa1, 0x78, 0x37, 0x76, 0x64, 0xb7,
0x90, 0x7f, 0x6d, 0x23, 0xcf, 0x9a, 0xac, 0xab, 0x44, 0x94, 0xe8, 0xc8, 0xa4, 0x63, 0x00, 0x06,
0x35, 0xb9, 0x67, 0xe5, 0x8d, 0xb3, 0xac, 0x81, 0x62, 0x31, 0xf6, 0x08, 0xd4, 0x0f, 0xd0, 0x63,
0x45, 0x64, 0xbe, 0x5e, 0x09, 0x74, 0x30, 0x21, 0xed, 0xc8, 0xc9, 0xbf, 0x84, 0x3c, 0x13, 0xb1,
0xe3, 0x06, 0x88, 0xdf, 0x79, 0xde, 0x64, 0x1d, 0x15, 0xc4, 0xef, 0x2f, 0x25, 0xd0, 0x6f, 0x39,
0x07, 0xdd, 0x0e, 0x50, 0x46, 0xd4, 0x9b, 0x4b, 0xfc, 0x83, 0x31, 0xc0, 0x19, 0x90, 0x5b, 0x09,
0xd4, 0xec, 0x0e, 0xa8, 0x72, 0xc1, 0xfa, 0x13, 0x76, 0x3c, 0x10, 0x23, 0x2f, 0xc7, 0xdc, 0x03,
0xfd, 0x08, 0x7a, 0xdd, 0x13, 0x3b, 0x79, 0x82, 0x1a, 0x2d, 0xa1, 0xb7, 0x30, 0xfb, 0x44, 0xcb,
0x2f, 0x91, 0xfc, 0x21, 0x7e, 0x5e, 0xe3, 0x2d, 0x1e, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x91,
0xcb, 0x59, 0x09, 0x99, 0x01, 0x00, 0x00,
}
package echo
type EchoTx struct {
Message string `json:"msg"`
}
package echo
import (
"reflect"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
// 定义本执行器支持的Action种类
const (
ActionPing = iota
ActionPang
)
// 定义本执行器生成的log类型
const (
TyLogPing = 100001
TyLogPang = 100002
)
var (
// 本执行器名称
EchoX = "echo"
// 定义本执行器支持的Action对应关系
actionName = map[string]int32{
"Ping": ActionPing,
"Pang": ActionPang,
}
// 定义本执行器的Log收据解析结构
logInfo = map[int64]*types.LogInfo{
TyLogPing: {reflect.TypeOf(PingLog{}), "PingLog"},
TyLogPang: {reflect.TypeOf(PangLog{}), "PangLog"},
}
)
var elog = log.New("module", EchoX)
func init() {
// 将本执行器添加到系统白名单
types.AllowUserExec = append(types.AllowUserExec, []byte(EchoX))
// 向系统注册本执行器类型
types.RegistorExecutor(EchoX, NewType())
}
// 定义本执行器类型
type EchoType struct {
types.ExecTypeBase
}
// 初始化本执行器类型
func NewType() *EchoType {
c := &EchoType{}
c.SetChild(c)
return c
}
// 返回本执行器的负载类型
func (b *EchoType) GetPayload() types.Message {
return &EchoAction{}
}
// 返回本执行器名称
func (b *EchoType) GetName() string {
return EchoX
}
// 返回本执行器中的action字典,支持双向查找
func (b *EchoType) GetTypeMap() map[string]int32 {
return actionName
}
// 返回本执行器的日志类型信息,用于rpc解析日志数据
func (b *EchoType) GetLogMap() map[int64]*types.LogInfo {
return logInfo
}
......@@ -3,6 +3,7 @@ package init
import (
_ "github.com/33cn/plugin/plugin/dapp/blackwhite" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/cert" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/echo" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/evm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/game" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/hashlock" //auto gen
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment