Commit 7c5ce435 authored by kingwang's avatar kingwang Committed by 33cn

update chain33 04/02

parent 0ba0605f
......@@ -223,16 +223,15 @@ func (acc *DB) ExecAddress(name string) string {
return address.ExecAddress(name)
}
// ExecDepositFrozen 执行
// ExecDepositFrozen 执行增发coins
func (acc *DB) ExecDepositFrozen(addr, execaddr string, amount int64) (*types.Receipt, error) {
if addr == execaddr {
return nil, types.ErrSendSameToRecv
}
//这个函数只有挖矿的合约才能调用
list := types.AllowDepositExec
allow := false
for _, exec := range list {
if acc.ExecAddress(string(exec)) == execaddr {
for _, exec := range types.GetMinerExecs() {
if acc.ExecAddress(exec) == execaddr {
allow = true
break
}
......
......@@ -274,12 +274,15 @@ function sync() {
function transfer() {
echo "=========== # transfer ============="
${CLI} account balance -a 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 -e coins
prebalance=$(${CLI} account balance -a 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 -e coins | jq -r ".balance")
${CLI} block last_header
curHeight=$(${CLI} block last_header | jq ".height")
echo "curheight=$curHeight"
hashes=()
for ((i = 0; i < 10; i++)); do
hash=$(${CLI} send coins transfer -a 1 -n test -t 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
hash=$(${CLI} send coins transfer -a 1 -n test -t 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 -k CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944)
echo "$hash"
hashes=("${hashes[@]}" "$hash")
done
......@@ -299,17 +302,27 @@ function transfer() {
fi
done
${CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e coins
${CLI} account balance -a 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 -e coins
local times=100
while true; do
balance=$(${CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e coins | jq -r ".balance")
echo "account balance is ${balance}, expect 10.0000 "
newbalance=$(${CLI} account balance -a 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4 -e coins | jq -r ".balance")
echo "newbalance balance is ${newbalance}"
balance=$(echo "$newbalance - $prebalance" | bc)
echo "account added balance is ${balance}, expect 10.0000 "
if [ "${balance}" != "10.0000" ]; then
block_wait 2
times=$((times - 1))
if [ $times -le 0 ]; then
echo "account balance transfer failed"
echo "account balance transfer failed, all tx list below:"
for ((i = 0; i < ${#hashes[*]}; i++)); do
echo "------the $i tx=${hashes[$i]}----------"
${CLI} tx query_hash -s "${hashes[$i]}"
done
echo "----------block info------------------"
lastheight=$(${CLI} block last_header | jq -r ".height")
${CLI} block get -s 1 -e "${lastheight}" -d 1
exit 1
fi
else
......
......@@ -819,7 +819,6 @@ func TestGRPC(t *testing.T) {
testGetBlocksGRPC(t, &grpcMock)
testGetLastHeaderGRPC(t, &grpcMock)
testCreateRawTransactionGRPC(t, &grpcMock)
testSendRawTransactionGRPC(t, &grpcMock)
testQueryTransactionGRPC(t, &grpcMock)
testSendTransactionGRPC(t, &grpcMock)
testGetTransactionByAddrGRPC(t, &grpcMock)
......@@ -1132,14 +1131,6 @@ func testQueryTransactionGRPC(t *testing.T, rpc *mockGRPCSystem) {
}
}
func testSendRawTransactionGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.Reply
err := rpc.newRpcCtx("SendRawTransaction", &types.SignedTx{}, &res)
if err != nil {
t.Error("Call SendRawTransaction Failed.", err)
}
}
func testCreateRawTransactionGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.UnsignTx
err := rpc.newRpcCtx("CreateRawTransaction",
......
......@@ -114,12 +114,6 @@ func (c *GrpcCtx) Run() (err error) {
*c.Res.(*types.UnsignTx) = *reply
}
errRet = err
case "SendRawTransaction":
reply, err := rpc.SendRawTransaction(context.Background(), c.Params.(*types.SignedTx))
if err == nil {
*c.Res.(*types.Reply) = *reply
}
errRet = err
case "QueryTransaction":
reply, err := rpc.QueryTransaction(context.Background(), c.Params.(*types.ReqHash))
if err == 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 commands
import (
"fmt"
"github.com/33cn/chain33/cmd/tools/strategy"
"github.com/33cn/chain33/cmd/tools/types"
"github.com/spf13/cobra"
)
//AdvanceCmd advance cmd
func AdvanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "advance",
Short: "Create executor project in advance mode",
Run: advanceCreate,
}
addAdvanceCreateFlag(cmd)
return cmd
}
func addAdvanceCreateFlag(cmd *cobra.Command) {
cmd.Flags().StringP("name", "n", "", "executor project and class name")
cmd.MarkFlagRequired("name")
cmd.Flags().StringP("action", "a", "", "executor action class name")
cmd.Flags().StringP("propfile", "p", "", "protobuf file path")
cmd.Flags().StringP("templatepath", "t", "", "template file path")
}
func advanceCreate(cmd *cobra.Command, args []string) {
configFolder := "config/"
projectName, _ := cmd.Flags().GetString("name")
className := projectName
actionName, _ := cmd.Flags().GetString("action")
if len(actionName) == 0 {
actionName = className + "Action"
}
propFile, _ := cmd.Flags().GetString("propfile")
if len(propFile) == 0 {
propFile = fmt.Sprintf("%s%s.proto", configFolder, projectName)
}
templateFile, _ := cmd.Flags().GetString("templatepath")
if len(templateFile) == 0 {
templateFile = fmt.Sprintf("%stemplate/", configFolder)
}
fmt.Println("Begin execute advance task")
fmt.Println("Config Path", configFolder)
fmt.Println("Project Name:", projectName)
fmt.Println("Class Name:", className)
fmt.Println("Action Class Name:", actionName)
fmt.Println("Protobuf File:", propFile)
fmt.Println("Template File Path:", templateFile)
s := strategy.New(types.KeyCreateAdvanceExecProject)
if s == nil {
fmt.Println(types.KeyCreateAdvanceExecProject, "Not support")
return
}
s.SetParam(types.KeyConfigFolder, configFolder)
s.SetParam(types.KeyProjectName, projectName)
s.SetParam(types.KeyClassName, className)
s.SetParam(types.KeyExecutorName, projectName)
s.SetParam(types.KeyActionName, actionName)
s.SetParam(types.KeyProtobufFile, propFile)
s.SetParam(types.KeyTemplateFilePath, templateFile)
s.Run()
}
// 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 commands
import (
"fmt"
"github.com/33cn/chain33/cmd/tools/strategy"
"github.com/33cn/chain33/cmd/tools/types"
"github.com/spf13/cobra"
)
//SimpleCmd 简单命令
func SimpleCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "simple",
Short: "Create simple executor project mode",
Run: simpleCreate,
}
addSimpleCreateFlag(cmd)
return cmd
}
func addSimpleCreateFlag(cmd *cobra.Command) {
cmd.Flags().StringP("name", "n", "", "executor project and class name")
cmd.MarkFlagRequired("name")
cmd.Flags().StringP("templatefile", "t", "", "template file path")
}
func simpleCreate(cmd *cobra.Command, args []string) {
projectName, _ := cmd.Flags().GetString("name")
className := projectName
templateFile, _ := cmd.Flags().GetString("templatefile")
if len(templateFile) == 0 {
templateFile = fmt.Sprintf("template/%s.proto", projectName)
}
s := strategy.New(types.KeyCreateSimpleExecProject)
if s == nil {
fmt.Println(types.KeyCreateSimpleExecProject, "Not support")
return
}
s.SetParam(types.KeyProjectName, projectName)
s.SetParam(types.KeyClassName, className)
s.SetParam(types.KeyTemplateFilePath, templateFile)
s.Run()
}
# type字段仅支持 consensus dapp store mempool
[mempool-price]
type = "mempool"
gitrepo = "github.com/33cn/plugin/plugin/mempool/price"
version=""
syntax = "proto3";
package types;
message DemoAction {
oneof value {
DemoHello hello = 1;
DemoEcho echo = 2;
}
int32 ty = 3;
}
message DemoHello {}
message DemoEcho {
string data = 1;
}
package executor
import (
ptypes "github.com/33cn/plugin/plugin/dapp/${EXECNAME}/types"
"github.com/33cn/chain33/types"
)
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/bin/sh
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
package commands
import "github.com/spf13/cobra"
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "${EXECNAME}",
Short: "${EXECNAME} show hello",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
AddMessageCmd(),
QueryMessageCmd(),
)
return cmd
}
func AddMessageCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "add a new message",
Run: addMessage,
}
addMessageFlags(cmd)
return cmd
}
func addMessageFlags(cmd *cobra.Command) {
}
func addMessage(cmd *cobra.Command, args []string) {
}
func QueryMessageCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Short: "query message",
Run: queryMessage,
}
queryMessageFlags(cmd)
return cmd
}
func queryMessageFlags(cmd *cobra.Command) {
}
func queryMessage(cmd *cobra.Command, args []string) {
}
package ${EXECNAME}
import (
"github.com/33cn/chain33/plugin/dapp/${EXECNAME}/commands"
"github.com/33cn/chain33/plugin/dapp/${EXECNAME}/executor"
pty "github.com/33cn/chain33/plugin/dapp/${EXECNAME}/types"
"github.com/33cn/chain33/pluginmgr"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: pty.${EXECNAME}X,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: rpc.Init,
})
}
\ No newline at end of file
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/bin/sh
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
package commands
import "github.com/spf13/cobra"
func Cmd() *cobra.Command {
return &cobra.Command{}
}
package executor
import (
"fmt"
log "github.com/33cn/chain33/common/log/log15"
ptypes "github.com/33cn/chain33/plugin/dapp/${CLASSNAME}/types"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
)
var (
ptylog = log.New("module", "execs.${CLASSNAME}")
)
var driverName = ptypes.${CLASSNAME}X
func init() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&${CLASSNAME}{}))
}
func Init(name string) {
drivers.Register(GetName(), newGame, 0)
}
type ${CLASSNAME} struct {
drivers.DriverBase
}
func new${CLASSNAME}() drivers.Driver {
t := &${CLASSNAME}{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
func GetName() string {
return new${CLASSNAME}().GetName()
}
func (u *${CLASSNAME}) GetDriverName() string {
return driverName
}
package unfreeze
import (
"github.com/33cn/plugin/plugin/dapp/${CLASSNAME}/commands"
"github.com/33cn/plugin/plugin/dapp/${CLASSNAME}/types"
"github.com/33cn/plugin/plugin/dapp/${CLASSNAME}/executor"
"github.com/33cn/chain33/pluginmgr"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.PackageName,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: nil,
})
}
package rpc
import (
ptypes "github.com/33cn/plugin/plugin/dapp/${EXECNAME}/types"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
)
type channelClient struct {
rpctypes.ChannelClient
}
type Jrpc struct {
cli *channelClient
}
type Grpc struct {
*channelClient
}
func Init(name string, s rpctypes.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
ptypes.RegisterTradeServer(s.GRPC(), grpc)
}
package types
import (
"github.com/33cn/chain33/types"
)
// action for executor
${ACTIONIDTEXT}
${TYLOGACTIONTYPE}
var (
logMap = ${LOGMAPTEXT}
typeMap = ${TYPEMAPTEXT}
)
func init() {
types.AllowUserExec = append(types.AllowUserExec, []byte(${EXECNAME}))
types.RegistorExecutor(types.${EXECNAME}, NewType())
}
type ${TYPENAME} struct {
types.ExecTypeBase
}
func NewType() *${TYPENAME} {
c := &${TYPENAME}{}
c.SetChild(c)
return c
}
func (t *${TYPENAME}) GetPayload() types.Message {
return &${ACTIONNAME}{}
}
func (t *${TYPENAME}) GetTypeMap() map[string]int32 {
return typeMap
}
func (t *${TYPENAME}) GetLogMap() map[int64]*types.LogInfo {
return logMap
}
\ No newline at end of file
......@@ -3,54 +3,6 @@
// license that can be found in the LICENSE file.
/*
Package main chain33开发者工具,主要提供以下功能:
1. 通过chain33.cpm.toml配置,指定需要下载的包,从远程下载到本地 import
2. 通过本地创建各种执行器工程,相关命令为 simple, advance
3. 扫描本地插件信息,更新引用关系
4. 通过本地创建完整的插件项目,可以选择simple模式和advance模式.
目录介绍
1. config目录为tools工具使用的配置目录
2. config/chain33.cpm.toml 是tools工具通过go vendor下载三方系统插件的配置
3. config/exec_header.template 是tools工具创建执行器过程中使用的代码模板
4. config/types_content.template 是tools工具创建执行器过程中使用的代码模板
5. config/template 目录是tools工具创建执行器过程中使用的代码模板
库包获取的步骤
简单执行器工程向导
高级执行器工程向导
文字替换规则:
${PROJECTNAME}: 设定的项目名称
${CLASSNAME}: 设定的执行器类名
${ACTIONNAME}: 执行器内部逻辑使用的
${EXECNAME}: 执行器的名称
${TYPENAME}:
自动创建文件:
exec.go : 执行器功能中
exec_local.go:
exec_del_local.go
使用步骤:
1. 按照proto3的语法格式,创建执行器使用的Action结构,参考结构如下
// actions
message DemoAction {
oneof value {
DemoCreate create = 1;
DemoRun play = 2;
DemoClose show = 3;
}
int32 ty = 6;
}
2. 实现Action中使用的所有类型,例如上面的DemoCreate、DemoRun、DemoClose
3. 将编辑好的协议文件保存到tools所在目录下的config内
4. 使用命令行生成
命令行说明:
示例:tools advance -n demo
-a --action 执行器中Action使用的类型名,如果不填则为执行器名称+Action,例如DemoAction
-n --name 执行器的项目名和类名,必填参数
-p --propfile 导入执行器类型的proto3协议模板,如果不填默认为config/执行器名称.proto
-t --templatepath 生成执行器项目的模板文件,不填默认为config/template下的所有文件
更新初始化文件:
扫描指定path目录下所有的插件,根据扫描到的结果重新更新consensus、dapp和、store、mempool的初始化文件 init.go
......
......@@ -11,55 +11,54 @@ calculator合约支持在区块链上进行整数加减乘除交易操作,同
syntax = "proto3";
package calculator;
//calculator 合约交易行为总类型
// calculator 合约交易行为总类型
message CalculatorAction {
oneof value {
Add add = 1;
Subtract sub = 2;
Multiply mul = 3;
Divide div = 4;
Add add = 1;
Subtract sub = 2;
Multiply mul = 3;
Divide div = 4;
}
int32 ty = 5;
}
message Add { //加法action类型
int32 summand = 1; //被加数
int32 addend = 2; //加数
message Add {
int32 summand = 1; //被加数
int32 addend = 2; //加数
}
message AddLog { //加法log类型
int32 sum = 1; //和
message AddLog {
int32 sum = 1; //和
}
message Subtract {
int32 minuend = 1; //被减数
int32 subtrahend = 2; //减数
int32 minuend = 1; //被减数
int32 subtrahend = 2; //减数
}
message SubLog {
int32 remainder = 1; //差
int32 remainder = 1; //差
}
message Multiply {
int32 faciend = 1; //被乘数
int32 multiplier = 2; //乘数
int32 faciend = 1; //被乘数
int32 multiplier = 2; //乘数
}
message MultiplyLog {
int32 product = 1; //积
int32 product = 1; //积
}
message Divide {
int32 dividend = 1; //被除数
int32 divisor = 2; //除数
int32 divisor = 2; //除数
}
message DivideLog {
int32 quotient = 1; //商
int32 remain = 2; //余数
int32 remain = 2; //余数
}
message ReqQueryCalcCount { //查询计算次数请求结构
message ReqQueryCalcCount {
string action = 1;
}
message ReplyQueryCalcCount { //查询计算次数响应结构
message ReplyQueryCalcCount {
int32 count = 1;
}
......@@ -78,7 +77,7 @@ service calculator {
### 代码生成
##### 生成基本代码
>使用chain33-tool,工具使用参考[文档]([开发步骤](https://github.com/33cn/chain33/blob/master/cmd/tools/doc/gendapp.md))
>使用chain33-tool,工具使用参考[文档](https://github.com/33cn/chain33/blob/master/cmd/tools/doc/gendapp.md)
```
//本例默认将calculator生成至官方plugin项目dapp目录下
$ chain33-tool gendapp -n calculator -p calculator.proto
......
......@@ -40,7 +40,7 @@ $ chain33-tool gendapp -n demo -p ./demo.proto -o github.com/33cn/chain33/plugin
### proto规范
* 定义合约交易行为结构,采用**oneof value**形式,且名称必须为**NameAction**格式,
如demo合约,定义echo和hello两种交易行为
```
```proto
message DemoAction {
oneof value {
DemoHello hello = 1;
......@@ -50,12 +50,12 @@ message DemoAction {
}
```
* package name设为合约名,适配后续生成目录结构
```
```proto
package demo;
```
* 定义service,直接以合约名作为名称
```
```proto
service demo {
}
```
......
......@@ -23,8 +23,6 @@ func main() {
func addCommands(rootCmd *cobra.Command) {
rootCmd.AddCommand(
commands.SimpleCmd(),
commands.AdvanceCmd(),
commands.ImportCmd(),
commands.UpdateInitCmd(),
commands.CreatePluginCmd(),
......
// 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 strategy
import (
"fmt"
"os"
"path/filepath"
"github.com/33cn/chain33/cmd/tools/tasks"
"github.com/33cn/chain33/cmd/tools/types"
"github.com/33cn/chain33/cmd/tools/util"
sysutil "github.com/33cn/chain33/util"
"github.com/pkg/errors"
)
type advanceCreateExecProjStrategy struct {
strategyBasic
projName string // 创建的执行器包名
execName string
clsName string // 执行器主体类名
actionName string // 执行器处理过程中的Action类名
propFile string // protobuf 源文件路径
templateFile string // 生成执行器的模板文件路径
outputFolder string // 生成执行器的输出目录
configFolder string // 应用运行的配置目录
}
func (ad *advanceCreateExecProjStrategy) Run() error {
fmt.Println("Begin run chain33 create executor project advance mode.")
defer fmt.Println("Run chain33 create executor project advance mode finish.")
ad.initMember()
if !ad.checkParamValid() {
return errors.New("InvalidParams")
}
return ad.runImpl()
}
func (ad *advanceCreateExecProjStrategy) checkParamValid() bool {
return true
}
func (ad *advanceCreateExecProjStrategy) initMember() {
if v, err := ad.getParam(types.KeyConfigFolder); err == nil {
ad.configFolder = v
}
if v, err := ad.getParam(types.KeyProjectName); err == nil {
ad.projName = v
}
if v, err := ad.getParam(types.KeyClassName); err == nil {
ad.clsName = v
}
if v, err := ad.getParam(types.KeyExecutorName); err == nil {
ad.execName = v
}
if v, err := ad.getParam(types.KeyActionName); err == nil {
ad.actionName, _ = sysutil.MakeStringToUpper(v, 0, 1)
}
if v, err := ad.getParam(types.KeyProtobufFile); err == nil {
ad.propFile = v
}
if v, err := ad.getParam(types.KeyTemplateFilePath); err == nil {
ad.templateFile = v
}
// 默认输出到chain33项目的plugin/dapp/目录下
var outputPath string
gopath := os.Getenv("GOPATH")
if len(gopath) > 0 {
outputPath = filepath.Join(gopath, "/src/github.com/33cn/chain33/plugin/dapp/")
}
if len(outputPath) > 0 && util.CheckPathExisted(outputPath) {
ad.outputFolder = fmt.Sprintf("%s/%s/", outputPath, ad.projName)
} else {
// 默认就在当前目录下
ad.outputFolder = fmt.Sprintf("output/%s/", ad.projName)
}
util.MakeDir(ad.outputFolder)
}
func (ad *advanceCreateExecProjStrategy) runImpl() error {
var err error
task := ad.buildTask()
for {
if task == nil {
break
}
err = task.Execute()
if err != nil {
mlog.Error("Execute command failed.", "error", err, "taskname", task.GetName())
break
}
task = task.Next()
}
return err
}
func (ad *advanceCreateExecProjStrategy) buildTask() tasks.Task {
taskSlice := make([]tasks.Task, 0)
taskSlice = append(taskSlice,
// 检查用户编写的protobuf文件是否存在
&tasks.CheckFileExistedTask{
FileName: ad.propFile,
},
// 将文件复制到输出目录下
&tasks.CopyTemplateToOutputTask{
TemplatePath: ad.templateFile,
OutputPath: ad.outputFolder,
ProjectName: ad.projName,
ClassName: ad.clsName,
},
&tasks.ReplaceTargetTask{
OutputPath: ad.outputFolder,
ProjectName: ad.projName,
ClassName: ad.clsName,
ActionName: ad.actionName,
ExecName: ad.execName,
},
&tasks.CreateDappSourceTask{
TemplatePath: ad.templateFile,
OutputPath: ad.outputFolder,
ProjectName: ad.projName,
ClsName: ad.clsName,
ActionName: ad.actionName,
TypeName: ad.clsName + "Type",
ExecuteName: ad.execName,
ProtoFile: ad.propFile,
ExecHeaderTempFile: ad.configFolder + "/exec_header.template",
TypeTempFile: ad.configFolder + "/types_content.template",
TypeOutputFile: ad.outputFolder + "ptypes/",
},
&tasks.FormatDappSourceTask{
OutputFolder: ad.outputFolder,
},
)
task := taskSlice[0]
sliceLen := len(taskSlice)
for n := 1; n < sliceLen; n++ {
task.SetNext(taskSlice[n])
task = taskSlice[n]
}
return taskSlice[0]
}
......@@ -253,10 +253,7 @@ func (im *importPackageStrategy) fetchPlugin(gitrepo, version string) error {
func (im *importPackageStrategy) fetchPluginPackage() error {
mlog.Info("下载插件源码包")
pwd := util.Pwd()
err := os.Chdir(im.projRootPath)
if err != nil {
return err
}
defer os.Chdir(pwd)
for _, plugins := range im.items {
for _, plugin := range plugins {
......
// 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 strategy
import "github.com/33cn/chain33/cmd/tools/tasks"
type simpleCreateExecProjStrategy struct {
strategyBasic
}
func (s *simpleCreateExecProjStrategy) Run() error {
mlog.Info("Begin run chain33 simple create dapp project.")
defer mlog.Info("Run chain33 simple create dapp project finish.")
if err := s.initMember(); err != nil {
return err
}
return s.runImpl()
}
func (s *simpleCreateExecProjStrategy) runImpl() error {
// 复制模板目录下的文件到指定的目标目录,同时替换掉文件名
// 遍历目标文件夹内所有文件,替换内部标签
// 执行shell命令,生成对应的 pb.go 文件
// 更新引用文件
var err error
task := s.buildTask()
for {
if task == nil {
break
}
err = task.Execute()
if err != nil {
mlog.Error("Execute command failed.", "error", err, "taskname", task.GetName())
break
}
task = task.Next()
}
return err
}
func (s *simpleCreateExecProjStrategy) initMember() error {
return nil
}
func (s *simpleCreateExecProjStrategy) buildTask() tasks.Task {
return nil
}
......@@ -32,18 +32,6 @@ func New(name string) Strategy {
params: make(map[string]string),
},
}
case types.KeyCreateSimpleExecProject:
return &simpleCreateExecProjStrategy{
strategyBasic: strategyBasic{
params: make(map[string]string),
},
}
case types.KeyCreateAdvanceExecProject:
return &advanceCreateExecProjStrategy{
strategyBasic: strategyBasic{
params: make(map[string]string),
},
}
case types.KeyUpdateInit:
return &updateInitStrategy{
strategyBasic: strategyBasic{
......
// 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 tasks
import (
"fmt"
"strings"
"github.com/33cn/chain33/cmd/tools/types"
"github.com/33cn/chain33/cmd/tools/util"
)
// CreateDappSourceTask 通过生成好的pb.go和预先设计的模板,生成反射程序源码
type CreateDappSourceTask struct {
TaskBase
TemplatePath string // 生成最终源码时的模板路径
OutputPath string
ProjectName string
ClsName string // 生成源码的类名
ActionName string // 生成源码的Action类名
TypeName string
ExecuteName string
ProtoFile string // 推导的原始proto文件
ExecHeaderTempFile string
TypeTempFile string
TypeOutputFile string
actionInfos []*actionInfoItem // Action中的成员变量名称PB格式
execHeaderTempContent string
}
//GetName 获取name
func (c *CreateDappSourceTask) GetName() string {
return "CreateDappSourceTask"
}
//Execute 执行
func (c *CreateDappSourceTask) Execute() error {
mlog.Info("Execute create build app source task.")
if err := c.init(); err != nil {
return err
}
if err := c.readActionMemberNames(); err != nil {
return err
}
if err := c.createExecFile(); err != nil {
return err
}
if err := c.createExecLocalFile(); err != nil {
return err
}
if err := c.createExecDelLocalFile(); err != nil {
return err
}
if err := c.createTypeExecuteFile(); err != nil {
return err
}
return nil
}
func (c *CreateDappSourceTask) init() error {
if !util.CheckFileIsExist(c.ExecHeaderTempFile) {
return fmt.Errorf("file %s not exist", c.ExecHeaderTempFile)
}
contentbt, err := util.ReadFile(c.ExecHeaderTempFile)
if err != nil {
return fmt.Errorf("read file %s failed. error %q", c.ExecHeaderTempFile, err)
}
content := strings.Replace(string(contentbt), types.TagClassName, c.ClsName, -1)
content = strings.Replace(content, types.TagExecName, c.ExecuteName, -1)
c.execHeaderTempContent = content
return nil
}
func (c *CreateDappSourceTask) readActionMemberNames() error {
var err error
pbContext, err := util.ReadFile(c.ProtoFile)
if err != nil {
return err
}
c.actionInfos, err = readDappActionFromProto(string(pbContext), c.ActionName)
return err
}
func (c *CreateDappSourceTask) createExecFile() error {
content := c.execHeaderTempContent
content += formatExecContent(c.actionInfos, c.ClsName)
fileName := fmt.Sprintf("%s/executor/exec.go", c.OutputPath)
_, err := util.WriteStringToFile(fileName, content)
if err != nil {
mlog.Error(fmt.Sprintf("Write to file %s failed. error %q", fileName, err))
return err
}
return nil
}
func (c *CreateDappSourceTask) createExecLocalFile() error {
content := c.execHeaderTempContent
content += formatExecLocalContent(c.actionInfos, c.ClsName)
fileName := fmt.Sprintf("%s/executor/exec_local.go", c.OutputPath)
_, err := util.WriteStringToFile(fileName, content)
if err != nil {
mlog.Error(fmt.Sprintf("Write to file %s failed. error %q", fileName, err))
return err
}
return nil
}
func (c *CreateDappSourceTask) createExecDelLocalFile() error {
content := c.execHeaderTempContent
content += formatExecDelLocalContent(c.actionInfos, c.ClsName)
fileName := fmt.Sprintf("%s/executor/exec_del_local.go", c.OutputPath)
_, err := util.WriteStringToFile(fileName, content)
if err != nil {
mlog.Error(fmt.Sprintf("Write to file %s failed. error %q", fileName, err))
return err
}
return nil
}
/**
createTypeExecuteFile 根据自己的需求,创建一个types中与执行器同名的Type对照关系
需要处理的内容:
1. 定义TyLogXXXX的常量,规则是 TyLog + 变量名称
2. 定义类型常量,规则是 ActionName + 变量名称
3. 实现GetLogMap()
4. 实现GetTypeMap()
*/
func (c *CreateDappSourceTask) createTypeExecuteFile() error {
logText := buildActionLogTypeText(c.actionInfos, c.ExecuteName) // ${TYLOGACTIONTYPE}
actionIDText := buildActionIDText(c.actionInfos, c.ExecuteName) // ${ACTIONIDTEXT}
logMapText := buildLogMapText() // ${LOGMAPTEXT}
typeMapText := buildTypeMapText(c.actionInfos, c.ExecuteName) // ${TYPEMAPTEXT}
replacePairs := []struct {
src string
dst string
}{
{src: types.TagTyLogActionType, dst: logText},
{src: types.TagActionIDText, dst: actionIDText},
{src: types.TagLogMapText, dst: logMapText},
{src: types.TagTypeMapText, dst: typeMapText},
{src: types.TagTypeName, dst: c.TypeName},
{src: types.TagExecName, dst: c.ExecuteName},
{src: types.TagActionName, dst: c.ActionName},
}
bcontent, err := util.ReadFile(c.TypeTempFile)
if err != nil {
return err
}
content := string(bcontent)
for _, pair := range replacePairs {
content = strings.Replace(content, pair.src, pair.dst, -1)
}
fileName := fmt.Sprintf("%s%s.go", c.TypeOutputFile, c.ClsName)
util.DeleteFile(fileName)
_, err = util.WriteStringToFile(fileName, content)
return err
}
......@@ -3,18 +3,3 @@
// license that can be found in the LICENSE file.
package tasks
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/33cn/chain33/cmd/tools/util"
)
func TestReplaceTarget(t *testing.T) {
fileName := "../config/template/executor/${CLASSNAME}.go.tmp"
bcontent, err := util.ReadFile(fileName)
assert.NoError(t, err)
t.Log(string(bcontent))
}
......@@ -12,6 +12,7 @@ import (
"sync"
"sync/atomic"
"time"
//"time"
pb "github.com/33cn/chain33/types"
......@@ -61,7 +62,7 @@ func NewDownloadJob(p2pcli *Cli, peers []*Peer) *DownloadJob {
job.busyPeer = make(map[string]*peerJob)
job.downloadPeers = peers
job.MaxJob = 2
job.MaxJob = 5
if len(peers) < 5 {
job.MaxJob = 10
}
......
......@@ -93,13 +93,15 @@ func NewNode(cfg *types.P2P) (*Node, error) {
}
seeds := MainNetSeeds
if types.IsTestNet() {
seeds = TestNetSeeds
}
if cfg.InnerSeedEnable {
seeds := MainNetSeeds
if types.IsTestNet() {
seeds = TestNetSeeds
}
for _, seed := range seeds {
node.innerSeeds.Store(seed, "inner")
for _, seed := range seeds {
node.innerSeeds.Store(seed, "inner")
}
}
for _, seed := range cfg.Seeds {
......
......@@ -160,26 +160,6 @@ func decodeTx(hexstr string) (*types.Transaction, error) {
return &tx, nil
}
// SendRawTransaction send rawtransaction by p2p
func (c *channelClient) SendRawTransaction(param *types.SignedTx) (*types.Reply, error) {
if param == nil {
err := types.ErrInvalidParam
log.Error("SendRawTransaction", "Error", err)
return nil, err
}
var tx types.Transaction
err := types.Decode(param.GetUnsign(), &tx)
if err == nil {
tx.Signature = &types.Signature{
Ty: param.GetTy(),
Pubkey: param.GetPubkey(),
Signature: param.GetSign(),
}
return c.SendTx(&tx)
}
return nil, err
}
// GetAddrOverview get overview of address
func (c *channelClient) GetAddrOverview(parm *types.ReqAddr) (*types.AddrOverview, error) {
err := address.CheckAddress(parm.Addr)
......
......@@ -172,54 +172,6 @@ func TestChannelClient_CreateRawTransaction(t *testing.T) {
testCreateRawTransactionCoinWithdraw(t)
}
func testSendRawTransactionNil(t *testing.T) {
client := newTestChannelClient()
_, err := client.SendRawTransaction(nil)
assert.Equal(t, types.ErrInvalidParam, err)
}
func testSendRawTransactionErr(t *testing.T) {
var param = types.SignedTx{
Unsign: []byte("123"),
Sign: []byte("123"),
Pubkey: []byte("123"),
Ty: 1,
}
client := newTestChannelClient()
_, err := client.SendRawTransaction(&param)
assert.NotEmpty(t, err)
}
func testSendRawTransactionOk(t *testing.T) {
transfer := &types.Transaction{
Execer: []byte(types.ExecName("ticket")),
}
payload := types.Encode(transfer)
api := new(mocks.QueueProtocolAPI)
client := &channelClient{
QueueProtocolAPI: api,
}
api.On("SendTx", mock.Anything).Return(nil, nil)
var param = types.SignedTx{
Unsign: payload,
Sign: []byte("123"),
Pubkey: []byte("123"),
Ty: 1,
}
_, err := client.SendRawTransaction(&param)
assert.Nil(t, err)
}
func TestChannelClient_SendRawTransaction(t *testing.T) {
testSendRawTransactionNil(t)
testSendRawTransactionOk(t)
testSendRawTransactionErr(t)
}
func testChannelClientGetAddrOverviewNil(t *testing.T) {
parm := &types.ReqAddr{
Addr: "abcde",
......
......@@ -80,11 +80,6 @@ func (g *Grpc) CreateRawTxGroup(ctx context.Context, in *pb.CreateTransactionGro
return &pb.UnsignTx{Data: reply}, nil
}
// SendRawTransaction send rawtransaction
func (g *Grpc) SendRawTransaction(ctx context.Context, in *pb.SignedTx) (*pb.Reply, error) {
return g.cli.SendRawTransaction(in)
}
// QueryTransaction query transaction by grpc
func (g *Grpc) QueryTransaction(ctx context.Context, in *pb.ReqHash) (*pb.TransactionDetail, error) {
return g.cli.QueryTx(in)
......
......@@ -988,17 +988,6 @@ func TestGetLastHeader(t *testing.T) {
// testCreateRawTransactionOk(t)
//}
//func testSendRawTransactionReject(t *testing.T) {
// var in *pb.SignedTx
//
// _, err := g.SendRawTransaction(getNokCtx(), in)
// assert.EqualError(t, err, "reject", "the erros should be reject")
//}
//func TestSendRawTransaction(t *testing.T) {
// testSendRawTransactionReject(t)
//}
//func testQueryTransactionReject(t *testing.T) {
// var in *pb.ReqHash
//
......@@ -1102,24 +1091,6 @@ func TestGrpc_CreateRawTxGroup(t *testing.T) {
assert.Equal(t, types.ErrTxGroupCountLessThanTwo, err)
}
func TestGrpc_SendRawTransaction(t *testing.T) {
transfer := &types.Transaction{
Execer: []byte(types.ExecName("ticket")),
}
payload := types.Encode(transfer)
qapi.On("SendTx", mock.Anything).Return(nil, nil)
var param = &types.SignedTx{
Unsign: payload,
Sign: []byte("123"),
Pubkey: []byte("123"),
Ty: 1,
}
_, err := g.SendRawTransaction(getOkCtx(), param)
assert.NoError(t, err)
}
func TestGrpc_GetAddrOverview(t *testing.T) {
_, err := g.GetAddrOverview(getOkCtx(), &types.ReqAddr{})
assert.Equal(t, err, types.ErrInvalidAddress)
......
......@@ -8,7 +8,6 @@ import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"time"
"github.com/33cn/chain33/common"
......@@ -83,36 +82,6 @@ func (c *Chain33) CreateNoBalanceTransaction(in *types.NoBalanceTx, result *stri
return nil
}
// SendRawTransaction send rawtransacion
func (c *Chain33) SendRawTransaction(in rpctypes.SignedTx, result *interface{}) error {
var stx types.SignedTx
var err error
stx.Pubkey, err = hex.DecodeString(in.Pubkey)
if err != nil {
return err
}
stx.Sign, err = hex.DecodeString(in.Sign)
if err != nil {
return err
}
stx.Unsign, err = hex.DecodeString(in.Unsign)
if err != nil {
return err
}
stx.Ty = in.Ty
reply, err := c.cli.SendRawTransaction(&stx)
if err != nil {
return err
}
if reply.IsOk {
*result = "0x" + hex.EncodeToString(reply.Msg)
return nil
}
return fmt.Errorf(string(reply.Msg))
}
// SendTransaction send transaction
func (c *Chain33) SendTransaction(in rpctypes.RawParm, result *interface{}) error {
var parm types.Transaction
......
......@@ -460,100 +460,6 @@ func TestChain33_CreateTxGroup(t *testing.T) {
assert.Nil(t, err)
}
func TestChain33_SendRawTransaction(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
// var result interface{}
api.On("SendTx", mock.Anything).Return()
testChain33 := newTestChain33(api)
var testResult interface{}
signedTx := rpctypes.SignedTx{
Unsign: "123",
Sign: "123",
Pubkey: "123",
Ty: 1,
}
err := testChain33.SendRawTransaction(signedTx, &testResult)
t.Log(err)
assert.Nil(t, testResult)
assert.NotNil(t, err)
// api.Called(1)
// mock.AssertExpectationsForObjects(t, api)
}
func TestChain33_SendRawTransactionSignError(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
// var result interface{}
api.On("SendTx", mock.Anything).Return()
testChain33 := newTestChain33(api)
var testResult interface{}
src := []byte("123")
pubkey := make([]byte, hex.EncodedLen(len(src)))
hex.Encode(pubkey, src)
signedTx := rpctypes.SignedTx{
Unsign: "123",
Sign: "123",
Pubkey: string(pubkey),
Ty: 1,
}
err := testChain33.SendRawTransaction(signedTx, &testResult)
t.Log(err)
assert.Nil(t, testResult)
assert.NotNil(t, err)
// api.Called(1)
// mock.AssertExpectationsForObjects(t, api)
}
func TestChain33_SendRawTransactionUnsignError(t *testing.T) {
reply := &types.Reply{IsOk: true}
api := new(mocks.QueueProtocolAPI)
// var result interface{}
api.On("SendTx", mock.Anything).Return(reply, nil)
testChain33 := newTestChain33(api)
var testResult interface{}
src := []byte("123")
pubkey := make([]byte, hex.EncodedLen(len(src)))
signkey := make([]byte, hex.EncodedLen(len(src)))
hex.Encode(pubkey, src)
hex.Encode(signkey, src)
signedTx := rpctypes.SignedTx{
Unsign: "123",
Sign: string(signkey),
Pubkey: string(pubkey),
Ty: 1,
}
err := testChain33.SendRawTransaction(signedTx, &testResult)
t.Log(err)
assert.Nil(t, testResult)
assert.NotNil(t, err)
tx := &types.Transaction{
To: "to",
}
txByte := types.Encode(tx)
unsign := make([]byte, hex.EncodedLen(len(txByte)))
hex.Encode(unsign, txByte)
signedTx = rpctypes.SignedTx{
Unsign: string(unsign),
Sign: string(signkey),
Pubkey: string(pubkey),
Ty: 1,
}
err = testChain33.SendRawTransaction(signedTx, &testResult)
t.Log(testResult)
assert.Nil(t, err)
assert.Equal(t, "0x", testResult)
//assert.NotNil(t, err)
// api.Called(1)
// mock.AssertExpectationsForObjects(t, api)
}
func TestChain33_SendTransaction(t *testing.T) {
if types.IsPara() {
t.Skip()
......
......@@ -14,6 +14,7 @@ import (
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
log "github.com/33cn/chain33/common/log/log15"
ty "github.com/33cn/chain33/system/store/mavl/db/types"
"github.com/33cn/chain33/types"
farm "github.com/dgryski/go-farm"
"github.com/golang/protobuf/proto"
......@@ -569,6 +570,13 @@ func updateGlobalMemTree(node *Node) {
Size: node.size,
}
if node.height == 0 {
if bytes.HasPrefix(node.key, ty.TicketPrefix) {
ticket := &ty.Ticket{}
err := proto.Unmarshal(node.value, ticket)
if err == nil && ticket.Status == ty.StatusCloseTicket { //ticket为close状态下不做存储
return
}
}
memN.data = make([][]byte, 4)
memN.data[3] = node.value
} else {
......@@ -594,6 +602,13 @@ func updateLocalMemTree(t *Tree, node *Node) {
Size: node.size,
}
if node.height == 0 {
if bytes.HasPrefix(node.key, ty.TicketPrefix) {
ticket := &ty.Ticket{}
err := proto.Unmarshal(node.value, ticket)
if err == nil && ticket.Status == ty.StatusCloseTicket { //ticket为close状态下不做存储
return
}
}
memN.data = make([][]byte, 4)
memN.data[3] = node.value
} else {
......
// 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 types
var (
// TicketPrefix ticket prefix
TicketPrefix = []byte("mavl-ticket-")
)
const (
// StatusNewTicket new ticket status
StatusNewTicket = 1
// StatusMinerTicket Miner ticket status
StatusMinerTicket = 2
// StatusCloseTicket Close ticket status
StatusCloseTicket = 3
)
......@@ -81,6 +81,8 @@ type Consensus struct {
Genesis string `protobuf:"bytes,4,opt,name=genesis" json:"genesis,omitempty"`
HotkeyAddr string `protobuf:"bytes,5,opt,name=hotkeyAddr" json:"hotkeyAddr,omitempty"`
ForceMining bool `protobuf:"varint,6,opt,name=forceMining" json:"forceMining,omitempty"`
// 配置挖矿的合约名单
MinerExecs []string `protobuf:"bytes,7,rep,name=minerExecs" json:"minerExecs,omitempty"`
}
// Wallet 配置
......
......@@ -20,15 +20,15 @@ import (
//区块链共识相关的参数,重要参数不要随便修改
var (
AllowUserExec = [][]byte{ExecerNone}
//AllowDepositExec 这里又限制了一次,因为挖矿的合约不会太多,所以这里配置死了,如果要扩展,需要改这里的代码
AllowDepositExec = [][]byte{[]byte("ticket")}
EmptyValue = []byte("FFFFFFFFemptyBVBiCj5jvE15pEiwro8TQRGnJSNsJF") //这字符串表示数据库中的空值
title string
mu sync.Mutex
titles = map[string]bool{}
chainConfig = make(map[string]interface{})
mver = make(map[string]*mversion)
coinSymbol = "bty"
//挖矿的合约名单,适配旧配置,默认ticket
minerExecs = []string{"ticket"}
EmptyValue = []byte("FFFFFFFFemptyBVBiCj5jvE15pEiwro8TQRGnJSNsJF") //这字符串表示数据库中的空值
title string
mu sync.Mutex
titles = map[string]bool{}
chainConfig = make(map[string]interface{})
mver = make(map[string]*mversion)
coinSymbol = "bty"
)
// coin conversation
......@@ -93,6 +93,17 @@ func GetP(height int64) *ChainParam {
return c
}
// GetMinerExecs 获取挖矿的合约名单
func GetMinerExecs() []string {
return minerExecs
}
func setMinerExecs(execs []string) {
if len(execs) > 0 {
minerExecs = execs
}
}
// GetFundAddr 获取基金账户地址
func GetFundAddr() string {
return MGStr("mver.consensus.fundKeyAddr", 0)
......@@ -260,6 +271,7 @@ func Init(t string, cfg *Config) {
if cfg.Exec.MaxExecFee < cfg.Mempool.MaxTxFee {
panic("config must meet: mempool.maxTxFee <= exec.maxExecFee")
}
setMinerExecs(cfg.Consensus.MinerExecs)
setMinFee(cfg.Exec.MinExecFee)
setChainConfig("FixTime", cfg.FixTime)
if cfg.Exec.MaxExecFee > 0 {
......
......@@ -1302,36 +1302,6 @@ func (_m *Chain33Client) SaveSeed(ctx context.Context, in *types.SaveSeedByPw, o
return r0, r1
}
// SendRawTransaction provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) SendRawTransaction(ctx context.Context, in *types.SignedTx, opts ...grpc.CallOption) (*types.Reply, error) {
_va := make([]interface{}, len(opts))
for _i := range opts {
_va[_i] = opts[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, in)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *types.Reply
if rf, ok := ret.Get(0).(func(context.Context, *types.SignedTx, ...grpc.CallOption) *types.Reply); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.Reply)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *types.SignedTx, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SendToAddress provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) SendToAddress(ctx context.Context, in *types.ReqWalletSendToAddress, opts ...grpc.CallOption) (*types.ReplyHash, error) {
_va := make([]interface{}, len(opts))
......
......@@ -20,8 +20,6 @@ service chain33 {
//交易接口
rpc CreateRawTransaction(CreateTx) returns (UnsignTx) {}
rpc CreateRawTxGroup(CreateTransactionGroup) returns (UnsignTx) {}
//发送签名后交易
rpc SendRawTransaction(SignedTx) returns (Reply) {}
// 根据哈希查询交易
rpc QueryTransaction(ReqHash) returns (TransactionDetail) {}
// 发送交易
......
......@@ -76,13 +76,6 @@ message NoBalanceTx {
string expire = 4;
}
message SignedTx {
bytes unsign = 1;
bytes sign = 2;
bytes pubkey = 3;
int32 ty = 4;
}
message Transaction {
bytes execer = 1;
bytes payload = 2;
......
......@@ -478,7 +478,7 @@ func ExecAndCheckBlockCB(qclient queue.Client, block *types.Block, txs []*types.
//ResetDatadir 重写datadir
func ResetDatadir(cfg *types.Config, datadir string) string {
// Check in case of paths like "/something/~/something/"
if datadir[:2] == "~/" {
if len(datadir) >= 2 && datadir[:2] == "~/" {
usr, err := user.Current()
if err != nil {
panic(err)
......@@ -486,7 +486,7 @@ func ResetDatadir(cfg *types.Config, datadir string) string {
dir := usr.HomeDir
datadir = filepath.Join(dir, datadir[2:])
}
if datadir[:6] == "$TEMP/" {
if len(datadir) >= 6 && datadir[:6] == "$TEMP/" {
dir, err := ioutil.TempDir("", "chain33datadir-")
if err != nil {
panic(err)
......
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