Commit 894cc1eb authored by liuyuhang's avatar liuyuhang Committed by 33cn

add test

parent 62469022
...@@ -3,280 +3,3 @@ ...@@ -3,280 +3,3 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package executor package executor
//import (
// "testing"
//
// "github.com/stretchr/testify/assert"
//
// "encoding/hex"
//
// "github.com/33cn/chain33/account"
// "github.com/33cn/chain33/common"
// "github.com/33cn/chain33/common/address"
// "github.com/33cn/chain33/common/crypto"
// dbm "github.com/33cn/chain33/common/db"
// "github.com/33cn/chain33/types"
// "github.com/33cn/chain33/util"
// pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
//)
//
//type execEnv struct {
// blockTime int64
// blockHeight int64
// difficulty uint64
//}
//
//var (
// Symbol = "TEST"
// AssetExecToken = "token"
// AssetExecPara = "paracross"
//
// PrivKeyA = "0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" // 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4
// PrivKeyB = "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" // 1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR
// PrivKeyC = "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" // 1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k
// PrivKeyD = "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71" // 1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs
// Nodes = [][]byte{
// []byte("1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"),
// []byte("1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR"),
// []byte("1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k"),
// []byte("1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs"),
// }
//)
//
//func TestUnfreeze(t *testing.T) {
// types.SetTitleOnlyForTest("chain33")
// total := int64(100000)
// accountA := types.Account{
// Balance: total,
// Frozen: 0,
// Addr: string(Nodes[0]),
// }
// accountB := types.Account{
// Balance: total,
// Frozen: 0,
// Addr: string(Nodes[1]),
// }
//
// execAddr := address.ExecAddress(pty.UnfreezeX)
// stateDB, _ := dbm.NewGoMemDB("1", "2", 100)
// _, ldb, kvdb := util.CreateTestDB()
//
// accA, _ := account.NewAccountDB(AssetExecPara, Symbol, stateDB)
// accA.SaveExecAccount(execAddr, &accountA)
//
// accB, _ := account.NewAccountDB(AssetExecPara, Symbol, stateDB)
// accB.SaveExecAccount(execAddr, &accountB)
//
// env := execEnv{
// 10,
// types.GetDappFork(pty.UnfreezeX, pty.ForkUnfreezeIDX),
// 1539918074,
// }
// ty := pty.UnfreezeType{}
//
// // 创建
// opt := &pty.FixAmount{Period: 10, Amount: 2}
// p1 := &pty.UnfreezeCreate{
// StartTime: 10,
// AssetExec: AssetExecPara,
// AssetSymbol: Symbol,
// TotalCount: 10000,
// Beneficiary: string(Nodes[1]),
// Means: "FixAmount",
// MeansOpt: &pty.UnfreezeCreate_FixAmount{FixAmount: opt},
// }
// createTx, err := ty.RPC_UnfreezeCreateTx(p1)
// if err != nil {
// t.Error("RPC_UnfreezeCreateTx", "err", err)
// }
// createTx, err = signTx(createTx, PrivKeyA)
// if err != nil {
// t.Error("RPC_UnfreezeCreateTx sign", "err", err)
// }
// exec := newUnfreeze()
// exec.SetStateDB(stateDB)
// exec.SetLocalDB(kvdb)
// exec.SetEnv(env.blockHeight, env.blockTime, env.difficulty)
// receipt, err := exec.Exec(createTx, int(1))
// assert.Nil(t, err)
// assert.NotNil(t, receipt)
// //t.Log(receipt)
// accTmp := accA.LoadExecAccount(accountA.Addr, execAddr)
// assert.Equal(t, total-p1.TotalCount, accTmp.Balance)
// assert.Equal(t, p1.TotalCount, accTmp.Frozen)
//
// receiptDate := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
// set, err := exec.ExecLocal(createTx, receiptDate, int(1))
// assert.Nil(t, err)
// assert.NotNil(t, set)
//
// req1 := &pty.ReqUnfreezes{
// Beneficiary: p1.Beneficiary,
// }
// reply, err := exec.Query("ListUnfreezeByBeneficiary", types.Encode(req1))
// assert.Nil(t, err)
// assert.NotNil(t, reply)
// resp, ok := reply.(*pty.ReplyUnfreezes)
// assert.True(t, ok)
// assert.Equal(t, 1, len(resp.Unfreeze))
// assert.Equal(t, string(unfreezeID(createTx.Hash())), resp.Unfreeze[0].UnfreezeID)
//
// // 提币
// p2 := &pty.UnfreezeWithdraw{
// UnfreezeID: hex.EncodeToString(createTx.Hash()),
// }
// withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx", "err", err)
// }
// withdrawTx, err = signTx(withdrawTx, PrivKeyB)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
// }
// blockTime := int64(10)
// exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime, env.difficulty)
// receipt, err = exec.Exec(withdrawTx, 1)
// assert.Nil(t, err)
// assert.NotNil(t, receipt)
// //t.Log(receipt)
// accATmp := accA.LoadExecAccount(accountA.Addr, execAddr)
// accBTmp := accB.LoadExecAccount(accountB.Addr, execAddr)
// assert.Equal(t, total-p1.TotalCount, accATmp.Balance)
//
// u := pty.Unfreeze{}
// e := types.Decode(receipt.KV[2].Value, &u)
// assert.Nil(t, e)
// assert.Equal(t, u.Remaining, accATmp.Frozen)
// assert.Equal(t, accountB.Balance+p1.TotalCount-u.Remaining, accBTmp.Balance)
//
// receiptDate2 := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
// set, err = exec.ExecLocal(withdrawTx, receiptDate2, int(1))
// assert.Nil(t, err)
// assert.NotNil(t, set)
//
// // 不是受益人提币
// {
// p2 := &pty.UnfreezeWithdraw{
// UnfreezeID: hex.EncodeToString(createTx.Hash()),
// }
// withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx", "err", err)
// }
// withdrawTx, err = signTx(withdrawTx, PrivKeyC)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
// }
// blockTime := int64(10)
// exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime, env.difficulty)
// receipt, err = exec.Exec(withdrawTx, 1)
// assert.Equal(t, pty.ErrNoPrivilege, err)
// assert.Nil(t, receipt)
// }
//
// // 不是创建者终止
// {
// p3 := &pty.UnfreezeTerminate{
// UnfreezeID: hex.EncodeToString(createTx.Hash()),
// }
// terminateTx, err := ty.RPC_UnfreezeTerminateTx(p3)
// if err != nil {
// t.Error("RPC_UnfreezeTerminateTx", "err", err)
// }
// terminateTx, err = signTx(terminateTx, PrivKeyC)
// if err != nil {
// t.Error("RPC_UnfreezeTerminateTx sign", "err", err)
// }
// receipt, err = exec.Exec(terminateTx, 1)
// assert.Equal(t, pty.ErrNoPrivilege, err)
// assert.Nil(t, receipt)
// }
//
// // 终止
// p3 := &pty.UnfreezeTerminate{
// UnfreezeID: hex.EncodeToString(createTx.Hash()),
// }
// terminateTx, err := ty.RPC_UnfreezeTerminateTx(p3)
// if err != nil {
// t.Error("RPC_UnfreezeTerminateTx", "err", err)
// }
// terminateTx, err = signTx(terminateTx, PrivKeyA)
// if err != nil {
// t.Error("RPC_UnfreezeTerminateTx sign", "err", err)
// }
// exec.SetEnv(env.blockHeight+2, env.blockTime+blockTime, env.difficulty)
// receipt, err = exec.Exec(terminateTx, 1)
// assert.Nil(t, err)
// assert.NotNil(t, receipt)
// //t.Log(receipt)
// accATmp = accA.LoadExecAccount(accountA.Addr, execAddr)
// assert.Equal(t, total+total, accATmp.Balance+accBTmp.Balance)
// assert.Equal(t, int64(0), accATmp.Frozen)
//
// receiptDate3 := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
// set, err = exec.ExecLocal(terminateTx, receiptDate3, int(1))
// assert.Nil(t, err)
// assert.NotNil(t, set)
//
// // 终止后不能继续提币
// {
// p2 := &pty.UnfreezeWithdraw{
// UnfreezeID: hex.EncodeToString(createTx.Hash()),
// }
// withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx", "err", err)
// }
// withdrawTx, err = signTx(withdrawTx, PrivKeyB)
// if err != nil {
// t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
// }
// blockTime := int64(10)
// exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime+blockTime, env.difficulty)
// receipt, err = exec.Exec(withdrawTx, 1)
// assert.Equal(t, pty.ErrUnfreezeEmptied, err)
// assert.Nil(t, receipt)
// }
//
// req := types.ReqString{Data: hex.EncodeToString(createTx.Hash())}
// _, err = exec.Query("GetUnfreeze", types.Encode(&req))
// assert.Nil(t, err)
//
// _, err = exec.Query("GetUnfreezeWithdraw", types.Encode(&req))
// assert.Nil(t, err)
//
// _, err = exec.ExecDelLocal(terminateTx, receiptDate3, int(1))
// assert.Nil(t, err)
//
// exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime, env.difficulty)
// _, err = exec.ExecDelLocal(withdrawTx, receiptDate2, int(1))
// assert.Nil(t, err)
//
// exec.SetEnv(env.blockHeight, env.blockTime+blockTime, env.difficulty)
// _, err = exec.ExecDelLocal(createTx, receiptDate, int(1))
// assert.Nil(t, err)
//
// ldb.Close()
//}
//
//func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
// signType := types.SECP256K1
// c, err := crypto.New(types.GetSignName(pty.UnfreezeX, signType))
// if err != nil {
// return tx, err
// }
//
// bytes, err := common.FromHex(hexPrivKey[:])
// if err != nil {
// return tx, err
// }
//
// privKey, err := c.PrivKeyFromBytes(bytes)
// if err != nil {
// return tx, err
// }
//
// tx.Sign(int32(signType), privKey)
// return tx, nil
//}
...@@ -77,7 +77,7 @@ func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) { ...@@ -77,7 +77,7 @@ func (a *action) propBoard(prob *auty.ProposalBoard) (*types.Receipt, error) {
value := types.Encode(cur) value := types.Encode(cur)
kv = append(kv, &types.KeyValue{Key: key, Value: value}) kv = append(kv, &types.KeyValue{Key: key, Value: value})
receiptLog := a.GetReceiptLog(nil, cur, auty.TyLogPropBoard) receiptLog := getReceiptLog(nil, cur, auty.TyLogPropBoard)
logs = append(logs, receiptLog) logs = append(logs, receiptLog)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
...@@ -138,7 +138,7 @@ func (a *action) rvkPropBoard(rvkProb *auty.RevokeProposalBoard) (*types.Receipt ...@@ -138,7 +138,7 @@ func (a *action) rvkPropBoard(rvkProb *auty.RevokeProposalBoard) (*types.Receipt
kv = append(kv, &types.KeyValue{Key: propBoardID(rvkProb.ProposalID), Value: types.Encode(&cur)}) kv = append(kv, &types.KeyValue{Key: propBoardID(rvkProb.ProposalID), Value: types.Encode(&cur)})
a.GetReceiptLog(pre, &cur, auty.TyLogRvkPropBoard) getReceiptLog(pre, &cur, auty.TyLogRvkPropBoard)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
} }
...@@ -253,7 +253,7 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt ...@@ -253,7 +253,7 @@ func (a *action) votePropBoard(voteProb *auty.VoteProposalBoard) (*types.Receipt
if cur.Res.Pass { if cur.Res.Pass {
ty = auty.TyLogTmintPropBoard ty = auty.TyLogTmintPropBoard
} }
receiptLog := a.GetReceiptLog(pre, &cur, int32(ty)) receiptLog := getReceiptLog(pre, &cur, int32(ty))
logs = append(logs, receiptLog) logs = append(logs, receiptLog)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
...@@ -324,7 +324,7 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types. ...@@ -324,7 +324,7 @@ func (a *action) tmintPropBoard(tmintProb *auty.TerminateProposalBoard) (*types.
kv = append(kv, &types.KeyValue{Key: propBoardID(tmintProb.ProposalID), Value: types.Encode(&cur)}) kv = append(kv, &types.KeyValue{Key: propBoardID(tmintProb.ProposalID), Value: types.Encode(&cur)})
a.GetReceiptLog(pre, &cur, auty.TyLogTmintPropBoard) getReceiptLog(pre, &cur, auty.TyLogTmintPropBoard)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
} }
...@@ -353,9 +353,9 @@ func (a *action) getStartHeightVoteAccount(addr string, height int64) (*types.Ac ...@@ -353,9 +353,9 @@ func (a *action) getStartHeightVoteAccount(addr string, height int64) (*types.Ac
return account[0], nil return account[0], nil
} }
// GetReceiptLog 根据提案信息获取log // getReceiptLog 根据提案信息获取log
// 状态变化: // 状态变化:
func (a *action) GetReceiptLog(pre, cur *auty.AutonomyProposalBoard, ty int32) *types.ReceiptLog { func getReceiptLog(pre, cur *auty.AutonomyProposalBoard, ty int32) *types.ReceiptLog {
log := &types.ReceiptLog{} log := &types.ReceiptLog{}
log.Ty = ty log.Ty = ty
r := &auty.ReceiptProposalBoard{Prev: pre, Current: cur} r := &auty.ReceiptProposalBoard{Prev: pre, Current: cur}
......
...@@ -9,12 +9,12 @@ import ( ...@@ -9,12 +9,12 @@ import (
"github.com/33cn/plugin/plugin/dapp/autonomy/commands" "github.com/33cn/plugin/plugin/dapp/autonomy/commands"
"github.com/33cn/plugin/plugin/dapp/autonomy/executor" "github.com/33cn/plugin/plugin/dapp/autonomy/executor"
"github.com/33cn/plugin/plugin/dapp/autonomy/rpc" "github.com/33cn/plugin/plugin/dapp/autonomy/rpc"
ptypes "github.com/33cn/plugin/plugin/dapp/autonomy/types" "github.com/33cn/plugin/plugin/dapp/autonomy/types"
) )
func init() { func init() {
pluginmgr.Register(&pluginmgr.PluginBase{ pluginmgr.Register(&pluginmgr.PluginBase{
Name: ptypes.PackageName, Name: types.AutonomyX,
ExecName: executor.GetName(), ExecName: executor.GetName(),
Exec: executor.Init, Exec: executor.Init,
Cmd: commands.AutonomyCmd, Cmd: commands.AutonomyCmd,
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode" "github.com/33cn/chain33/util/testnode"
pty "github.com/33cn/plugin/plugin/dapp/blackwhite/types" auty "github.com/33cn/plugin/plugin/dapp/autonomy/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
...@@ -38,13 +38,11 @@ func TestJRPCChannel(t *testing.T) { ...@@ -38,13 +38,11 @@ func TestJRPCChannel(t *testing.T) {
testCases := []struct { testCases := []struct {
fn func(*testing.T, *jsonclient.JSONClient) error fn func(*testing.T, *jsonclient.JSONClient) error
}{ }{
{fn: testCreateRawTxCmd}, {fn: testPropBoardTxCmd},
{fn: testPlayRawTxCmd}, {fn: testRevokeProposalBoardTxCmd},
{fn: testShowRawTxCmd}, {fn: testVoteProposalBoardTxCmd},
{fn: testTimeoutDoneTxCmd}, {fn: testTerminateProposalBoardTxCmd},
{fn: testRoundInfoCmd}, {fn: testGetProposalBoardCmd},
{fn: testRoundListCmd},
{fn: testLoopResultCmd},
} }
for index, testCase := range testCases { for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient) err := testCase.fn(t, jrpcClient)
...@@ -58,58 +56,36 @@ func TestJRPCChannel(t *testing.T) { ...@@ -58,58 +56,36 @@ func TestJRPCChannel(t *testing.T) {
} }
} }
func testCreateRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testPropBoardTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &pty.BlackwhiteCreateTxReq{} params := &auty.ProposalBoard{}
var res string var res string
return jrpc.Call("blackwhite.BlackwhiteCreateTx", params, &res) return jrpc.Call("autonomy.PropBoardTx", params, &res)
} }
func testPlayRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testRevokeProposalBoardTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &pty.BlackwhitePlayTxReq{} params := &auty.RevokeProposalBoard{}
var res string var res string
return jrpc.Call("blackwhite.BlackwhitePlayTx", params, &res) return jrpc.Call("autonomy.RevokeProposalBoardTx", params, &res)
} }
func testShowRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testVoteProposalBoardTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &pty.BlackwhiteShowTxReq{} params := &auty.VoteProposalBoard{}
var res string var res string
return jrpc.Call("blackwhite.BlackwhiteShowTx", params, &res) return jrpc.Call("autonomy.VoteProposalBoardTx", params, &res)
} }
func testTimeoutDoneTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testTerminateProposalBoardTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
params := &pty.BlackwhiteTimeoutDoneTxReq{} params := &auty.TerminateProposalBoard{}
var res string var res string
return jrpc.Call("blackwhite.BlackwhiteTimeoutDoneTx", params, &res) return jrpc.Call("autonomy.TerminateProposalBoardTx", params, &res)
} }
func testRoundInfoCmd(t *testing.T, jrpc *jsonclient.JSONClient) error { func testGetProposalBoardCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{} var rep interface{}
var params rpctypes.Query4Jrpc var params rpctypes.Query4Jrpc
req := &pty.ReqBlackwhiteRoundInfo{} req := &auty.ReqQueryProposalBoard{}
params.FuncName = pty.GetBlackwhiteRoundInfo params.FuncName = auty.GetProposalBoard
params.Payload = types.MustPBToJSON(req) params.Payload = types.MustPBToJSON(req)
rep = &pty.ReplyBlackwhiteRoundInfo{} rep = &auty.ReplyQueryProposalBoard{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testRoundListCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.ReqBlackwhiteRoundList{}
params.FuncName = pty.GetBlackwhiteByStatusAndAddr
params.Payload = types.MustPBToJSON(req)
rep = &pty.ReplyBlackwhiteRoundList{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testLoopResultCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.ReqLoopResult{}
params.FuncName = pty.GetBlackwhiteloopResult
params.Payload = types.MustPBToJSON(req)
rep = &pty.ReplyLoopResults{}
return jrpc.Call("Chain33.Query", params, rep) return jrpc.Call("Chain33.Query", params, rep)
} }
...@@ -83,8 +83,6 @@ const ( ...@@ -83,8 +83,6 @@ const (
//建议用github的组织名称,或者用户名字开头, 再加上自己的插件的名字 //建议用github的组织名称,或者用户名字开头, 再加上自己的插件的名字
//如果发生重名,可以通过配置文件修改这些名字 //如果发生重名,可以通过配置文件修改这些名字
var ( var (
PackageName = "chain33.autonomy"
RPCName = "Chain33.Autonomy"
AutonomyX = "autonomy" AutonomyX = "autonomy"
ExecerAutonomy = []byte(AutonomyX) ExecerAutonomy = []byte(AutonomyX)
) )
...@@ -16,9 +16,10 @@ var tlog = log.New("module", name) ...@@ -16,9 +16,10 @@ var tlog = log.New("module", name)
func init() { func init() {
name = AutonomyX name = AutonomyX
types.AllowUserExec = append(types.AllowUserExec, []byte(AutonomyX)) types.AllowUserExec = append(types.AllowUserExec, []byte(name))
// init executor type // init executor type
types.RegistorExecutor(name, NewType()) types.RegistorExecutor(name, NewType())
types.RegisterDappFork(name, "Enable", 1)
} }
//getRealExecName //getRealExecName
......
package init package init
import ( import (
_ "github.com/33cn/plugin/plugin/dapp/autonomy" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/blackwhite" //auto gen _ "github.com/33cn/plugin/plugin/dapp/blackwhite" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/cert" //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/echo" //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