Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
7d9726f6
Commit
7d9726f6
authored
Dec 21, 2018
by
张振华
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into guess
parents
d6f96f30
9ae6ffa1
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
2175 additions
and
18 deletions
+2175
-18
bug_report.md
.github/ISSUE_TEMPLATE/bug_report.md
+38
-0
custom.md
.github/ISSUE_TEMPLATE/custom.md
+10
-0
feature_request.md
.github/ISSUE_TEMPLATE/feature_request.md
+20
-0
echo.go
plugin/dapp/echo/commands/echo.go
+80
-0
doc.go
plugin/dapp/echo/doc/doc.go
+5
-0
check.go
plugin/dapp/echo/executor/check.go
+8
-0
echo.go
plugin/dapp/echo/executor/echo.go
+48
-0
exec.go
plugin/dapp/echo/executor/exec.go
+30
-0
exec_del_local.go
plugin/dapp/echo/executor/exec_del_local.go
+52
-0
exec_local.go
plugin/dapp/echo/executor/exec_local.go
+44
-0
query.go
plugin/dapp/echo/executor/query.go
+34
-0
plugin.go
plugin/dapp/echo/plugin.go
+23
-0
echo.proto
plugin/dapp/echo/proto/echo.proto
+41
-0
rpc.go
plugin/dapp/echo/rpc/rpc.go
+46
-0
echo.go
plugin/dapp/echo/types/echo/echo.go
+65
-0
echo.pb.go
plugin/dapp/echo/types/echo/echo.pb.go
+336
-0
tx.go
plugin/dapp/echo/types/echo/tx.go
+6
-0
types.go
plugin/dapp/echo/types/echo/types.go
+75
-0
init.go
plugin/dapp/init/init.go
+1
-0
multisig.go
plugin/dapp/multisig/executor/multisig.go
+1
-1
exec_del_local.go
plugin/dapp/paracross/executor/exec_del_local.go
+3
-2
exec_local.go
plugin/dapp/paracross/executor/exec_local.go
+3
-2
utils.go
plugin/dapp/token/commands/utils.go
+1
-1
query.go
plugin/dapp/trade/executor/query.go
+2
-0
trade.go
plugin/dapp/trade/executor/trade.go
+1
-1
.travis.yml
vendor/github.com/33cn/chain33/.travis.yml
+5
-5
db.go
vendor/github.com/33cn/chain33/common/db/db.go
+1
-2
db_test.go
vendor/github.com/33cn/chain33/common/db/db_test.go
+24
-0
go_level_db_test.go
vendor/github.com/33cn/chain33/common/db/go_level_db_test.go
+12
-0
list_helper.go
vendor/github.com/33cn/chain33/common/db/list_helper.go
+0
-1
count.go
vendor/github.com/33cn/chain33/common/db/table/count.go
+93
-0
count_test.go
vendor/github.com/33cn/chain33/common/db/table/count_test.go
+36
-0
error.go
vendor/github.com/33cn/chain33/common/db/table/error.go
+17
-0
query.go
vendor/github.com/33cn/chain33/common/db/table/query.go
+113
-0
table.go
vendor/github.com/33cn/chain33/common/db/table/table.go
+457
-0
table_test.go
vendor/github.com/33cn/chain33/common/db/table/table_test.go
+439
-0
utils.go
...thub.com/33cn/chain33/system/dapp/commands/types/utils.go
+1
-1
eventprocess.go
...or/github.com/33cn/chain33/system/mempool/eventprocess.go
+1
-1
util.go
vendor/github.com/33cn/chain33/util/util.go
+3
-1
No files found.
.github/ISSUE_TEMPLATE/bug_report.md
0 → 100644
View file @
7d9726f6
---
name
:
Bug report
about
:
Create a report to help us improve
title
:
'
'
labels
:
'
'
assignees
:
'
'
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1.
Go to '...'
2.
Click on '....'
3.
Scroll down to '....'
4.
See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
-
OS:
[
e.g. iOS
]
-
Browser
[
e.g. chrome, safari
]
-
Version
[
e.g. 22
]
**Smartphone (please complete the following information):**
-
Device:
[
e.g. iPhone6
]
-
OS:
[
e.g. iOS8.1
]
-
Browser
[
e.g. stock browser, safari
]
-
Version
[
e.g. 22
]
**Additional context**
Add any other context about the problem here.
.github/ISSUE_TEMPLATE/custom.md
0 → 100644
View file @
7d9726f6
---
name
:
Custom issue template
about
:
Describe this issue template's purpose here.
title
:
'
'
labels
:
'
'
assignees
:
'
'
---
.github/ISSUE_TEMPLATE/feature_request.md
0 → 100644
View file @
7d9726f6
---
name
:
Feature request
about
:
Suggest an idea for this project
title
:
'
'
labels
:
'
'
assignees
:
'
'
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when
[
...
]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
plugin/dapp/echo/commands/echo.go
0 → 100644
View file @
7d9726f6
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"
)
// EchoCmd 本执行器的命令行初始化总入口
func
EchoCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"echo"
,
Short
:
"echo commandline interface"
,
Args
:
cobra
.
MinimumNArgs
(
1
),
}
cmd
.
AddCommand
(
QueryCmd
(),
// 查询消息记录
// 如果有其它命令,在这里加入
)
return
cmd
}
// QueryCmd query 命令
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
))
}
plugin/dapp/echo/doc/doc.go
0 → 100644
View file @
7d9726f6
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
plugin/dapp/echo/executor/check.go
0 → 100644
View file @
7d9726f6
package
executor
import
"github.com/33cn/chain33/types"
// CheckTx 本执行器不做任何校验
func
(
h
*
Echo
)
CheckTx
(
tx
*
types
.
Transaction
,
index
int
)
error
{
return
nil
}
plugin/dapp/echo/executor/echo.go
0 → 100644
View file @
7d9726f6
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
(
// KeyPrefixPing ping 前缀
KeyPrefixPing
=
"mavl-echo-ping:%s"
// KeyPrefixPang pang 前缀
KeyPrefixPang
=
"mavl-echo-pang:%s"
// KeyPrefixPingLocal local ping 前缀
KeyPrefixPingLocal
=
"LODB-echo-ping:%s"
// KeyPrefixPangLocal local pang 前缀
KeyPrefixPangLocal
=
"LODB-echo-pang:%s"
)
// init 初始化时通过反射获取本执行器的方法列表
func
init
()
{
ety
:=
types
.
LoadExecutorType
(
echotypes
.
EchoX
)
ety
.
InitFuncList
(
types
.
ListMethod
(
&
Echo
{}))
}
// Init 本执行器的初始化动作,向系统注册本执行器,这里生效高度暂写为0
func
Init
(
name
string
,
sub
[]
byte
)
{
dapp
.
Register
(
echotypes
.
EchoX
,
newEcho
,
0
)
}
// Echo 定义执行器对象
type
Echo
struct
{
dapp
.
DriverBase
}
// 执行器对象初始化包装逻辑,后面的两步设置子对象和设置执行器类型必不可少
func
newEcho
()
dapp
.
Driver
{
c
:=
&
Echo
{}
c
.
SetChild
(
c
)
c
.
SetExecutorType
(
types
.
LoadExecutorType
(
echotypes
.
EchoX
))
return
c
}
// GetDriverName 返回本执行器驱动名称
func
(
h
*
Echo
)
GetDriverName
()
string
{
return
echotypes
.
EchoX
}
plugin/dapp/echo/executor/exec.go
0 → 100644
View file @
7d9726f6
package
executor
import
(
"fmt"
"github.com/33cn/chain33/types"
echotypes
"github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// Exec_Ping 执行 ping 类型交易
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
}
// Exec_Pang 执行 pang 类型交易
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
}
plugin/dapp/echo/executor/exec_del_local.go
0 → 100644
View file @
7d9726f6
package
executor
import
(
"fmt"
"github.com/33cn/chain33/types"
echotypes
"github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// ExecDelLocal_Ping 交易执行成功,将本消息对应的数值减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
--
}
val
:=
types
.
Encode
(
&
pingLog
)
if
pingLog
.
Count
==
0
{
val
=
nil
}
kv
:=
[]
*
types
.
KeyValue
{{
Key
:
localKey
,
Value
:
val
}}
return
&
types
.
LocalDBSet
{
KV
:
kv
},
nil
}
// ExecDelLocal_Pang 交易执行成功,将本消息对应的数值减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
--
}
val
:=
types
.
Encode
(
&
pangLog
)
if
pangLog
.
Count
==
0
{
val
=
nil
}
kv
:=
[]
*
types
.
KeyValue
{{
Key
:
localKey
,
Value
:
val
}}
return
&
types
.
LocalDBSet
{
KV
:
kv
},
nil
}
plugin/dapp/echo/executor/exec_local.go
0 → 100644
View file @
7d9726f6
package
executor
import
(
"fmt"
"github.com/33cn/chain33/types"
echotypes
"github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// ExecLocal_Ping 交易执行成功,将本消息对应的数值加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
++
kv
:=
[]
*
types
.
KeyValue
{{
Key
:
localKey
,
Value
:
types
.
Encode
(
&
pingLog
)}}
return
&
types
.
LocalDBSet
{
KV
:
kv
},
nil
}
// ExecLocal_Pang 交易执行成功,将本消息对应的数值加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
++
kv
:=
[]
*
types
.
KeyValue
{{
Key
:
localKey
,
Value
:
types
.
Encode
(
&
pangLog
)}}
return
&
types
.
LocalDBSet
{
KV
:
kv
},
nil
}
plugin/dapp/echo/executor/query.go
0 → 100644
View file @
7d9726f6
package
executor
import
(
"fmt"
"github.com/33cn/chain33/types"
echotypes
"github.com/33cn/plugin/plugin/dapp/echo/types/echo"
)
// Query_GetPing 查询 ping 次数
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
}
// Query_GetPang 查询 pang 次数
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
}
plugin/dapp/echo/plugin.go
0 → 100644
View file @
7d9726f6
// 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
,
})
}
plugin/dapp/echo/proto/echo.proto
0 → 100644
View file @
7d9726f6
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
plugin/dapp/echo/rpc/rpc.go
0 → 100644
View file @
7d9726f6
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"
)
// Jrpc 对外提供服务的RPC接口总体定义
type
Jrpc
struct
{
cli
*
channelClient
}
// RPC接口的本地实现
type
channelClient
struct
{
rpctypes
.
ChannelClient
}
// Init 注册 rpc 接口
func
Init
(
name
string
,
s
rpctypes
.
RPCServer
)
{
cli
:=
&
channelClient
{}
// 为了简单起见,这里只注册Jrpc,如果提供grpc的话也在这里注册
cli
.
Init
(
name
,
s
,
&
Jrpc
{
cli
:
cli
},
nil
)
}
// QueryPing 本合约的查询操作可以使用通用的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
}
// QueryPing 本地具体实现逻辑
func
(
c
*
channelClient
)
QueryPing
(
ctx
context
.
Context
,
queryParam
*
echotypes
.
Query
)
(
types
.
Message
,
error
)
{
return
c
.
Query
(
echotypes
.
EchoX
,
"GetPing"
,
queryParam
)
}
plugin/dapp/echo/types/echo/echo.go
0 → 100644
View file @
7d9726f6
package
echo
import
(
"encoding/json"
"math/rand"
"strings"
"time"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
)
// CreateTx 创建交易
func
(
e
*
Type
)
CreateTx
(
action
string
,
message
json
.
RawMessage
)
(
*
types
.
Transaction
,
error
)
{
elog
.
Debug
(
"echo.CreateTx"
,
"action"
,
action
)
// 只接受ping/pang两种交易操作
if
action
==
"ping"
||
action
==
"pang"
{
var
param
Tx
err
:=
json
.
Unmarshal
(
message
,
&
param
)
if
err
!=
nil
{
elog
.
Error
(
"CreateTx"
,
"Error"
,
err
)
return
nil
,
types
.
ErrInvalidParam
}
return
createPingTx
(
action
,
&
param
)
}
return
nil
,
types
.
ErrNotSupport
}
func
createPingTx
(
op
string
,
parm
*
Tx
)
(
*
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
*
Tx
)
(
*
EchoAction
,
error
)
{
pingAction
:=
&
Ping
{
Msg
:
parm
.
Message
}
action
:=
&
EchoAction
{
Value
:
&
EchoAction_Ping
{
Ping
:
pingAction
},
Ty
:
ActionPing
,
}
return
action
,
nil
}
func
getPangAction
(
parm
*
Tx
)
(
*
EchoAction
,
error
)
{
pangAction
:=
&
Pang
{
Msg
:
parm
.
Message
}
action
:=
&
EchoAction
{
Value
:
&
EchoAction_Pang
{
Pang
:
pangAction
},
Ty
:
ActionPang
,
}
return
action
,
nil
}
plugin/dapp/echo/types/echo/echo.pb.go
0 → 100644
View file @
7d9726f6
// 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
,
}
plugin/dapp/echo/types/echo/tx.go
0 → 100644
View file @
7d9726f6
package
echo
// Tx echo 交易结构
type
Tx
struct
{
Message
string
`json:"msg"`
}
plugin/dapp/echo/types/echo/types.go
0 → 100644
View file @
7d9726f6
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 本执行器名称
EchoX
=
"echo"
// 定义本执行器支持的Action对应关系
actionName
=
map
[
string
]
int32
{
"Ping"
:
ActionPing
,
"Pang"
:
ActionPang
,
}
// 定义本执行器的Log收据解析结构
logInfo
=
map
[
int64
]
*
types
.
LogInfo
{
TyLogPing
:
{
Ty
:
reflect
.
TypeOf
(
PingLog
{}),
Name
:
"PingLog"
},
TyLogPang
:
{
Ty
:
reflect
.
TypeOf
(
PangLog
{}),
Name
:
"PangLog"
},
}
)
var
elog
=
log
.
New
(
"module"
,
EchoX
)
func
init
()
{
// 将本执行器添加到系统白名单
types
.
AllowUserExec
=
append
(
types
.
AllowUserExec
,
[]
byte
(
EchoX
))
// 向系统注册本执行器类型
types
.
RegistorExecutor
(
EchoX
,
NewType
())
}
// Type 定义本执行器类型
type
Type
struct
{
types
.
ExecTypeBase
}
// NewType 初始化本执行器类型
func
NewType
()
*
Type
{
c
:=
&
Type
{}
c
.
SetChild
(
c
)
return
c
}
// GetPayload 返回本执行器的负载类型
func
(
b
*
Type
)
GetPayload
()
types
.
Message
{
return
&
EchoAction
{}
}
// GetName 返回本执行器名称
func
(
b
*
Type
)
GetName
()
string
{
return
EchoX
}
// GetTypeMap 返回本执行器中的action字典,支持双向查找
func
(
b
*
Type
)
GetTypeMap
()
map
[
string
]
int32
{
return
actionName
}
// GetLogMap 返回本执行器的日志类型信息,用于rpc解析日志数据
func
(
b
*
Type
)
GetLogMap
()
map
[
int64
]
*
types
.
LogInfo
{
return
logInfo
}
plugin/dapp/init/init.go
View file @
7d9726f6
...
...
@@ -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/guess"
//auto gen
...
...
plugin/dapp/multisig/executor/multisig.go
View file @
7d9726f6
...
...
@@ -887,7 +887,7 @@ func (m *MultiSig) getMultiSigAccAssets(multiSigAddr string, assets *mty.Assets)
}
var
acc1
*
types
.
Account
execaddress
:=
dapp
.
ExecAddress
(
m
.
GetName
(
))
execaddress
:=
dapp
.
ExecAddress
(
types
.
ExecName
(
m
.
GetName
()
))
acc1
=
acc
.
LoadExecAccount
(
multiSigAddr
,
execaddress
)
return
acc1
,
nil
}
...
...
plugin/dapp/paracross/executor/exec_del_local.go
View file @
7d9726f6
...
...
@@ -5,6 +5,7 @@
package
executor
import
(
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
pt
"github.com/33cn/plugin/plugin/dapp/paracross/types"
)
...
...
@@ -18,7 +19,7 @@ func (e *Paracross) ExecDelLocal_Commit(payload *pt.ParacrossCommitAction, tx *t
types
.
Decode
(
log
.
Log
,
&
g
)
var
r
pt
.
ParacrossTx
r
.
TxHash
=
string
(
tx
.
Hash
())
r
.
TxHash
=
common
.
ToHex
(
tx
.
Hash
())
set
.
KV
=
append
(
set
.
KV
,
&
types
.
KeyValue
{
Key
:
calcLocalTxKey
(
g
.
Status
.
Title
,
g
.
Status
.
Height
,
tx
.
From
()),
Value
:
nil
})
}
else
if
log
.
Ty
==
pt
.
TyLogParacrossCommitDone
{
var
g
pt
.
ReceiptParacrossDone
...
...
@@ -41,7 +42,7 @@ func (e *Paracross) ExecDelLocal_Commit(payload *pt.ParacrossCommitAction, tx *t
types
.
Decode
(
log
.
Log
,
&
g
)
var
r
pt
.
ParacrossTx
r
.
TxHash
=
string
(
tx
.
Hash
())
r
.
TxHash
=
common
.
ToHex
(
tx
.
Hash
())
set
.
KV
=
append
(
set
.
KV
,
&
types
.
KeyValue
{
Key
:
calcLocalTxKey
(
g
.
Status
.
Title
,
g
.
Status
.
Height
,
tx
.
From
()),
Value
:
nil
})
}
}
...
...
plugin/dapp/paracross/executor/exec_local.go
View file @
7d9726f6
...
...
@@ -7,6 +7,7 @@ package executor
import
(
"bytes"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
pt
"github.com/33cn/plugin/plugin/dapp/paracross/types"
...
...
@@ -21,7 +22,7 @@ func (e *Paracross) ExecLocal_Commit(payload *pt.ParacrossCommitAction, tx *type
types
.
Decode
(
log
.
Log
,
&
g
)
var
r
pt
.
ParacrossTx
r
.
TxHash
=
string
(
tx
.
Hash
())
r
.
TxHash
=
common
.
ToHex
(
tx
.
Hash
())
set
.
KV
=
append
(
set
.
KV
,
&
types
.
KeyValue
{
Key
:
calcLocalTxKey
(
g
.
Status
.
Title
,
g
.
Status
.
Height
,
tx
.
From
()),
Value
:
types
.
Encode
(
&
r
)})
}
else
if
log
.
Ty
==
pt
.
TyLogParacrossCommitDone
{
var
g
pt
.
ReceiptParacrossDone
...
...
@@ -43,7 +44,7 @@ func (e *Paracross) ExecLocal_Commit(payload *pt.ParacrossCommitAction, tx *type
types
.
Decode
(
log
.
Log
,
&
g
)
var
r
pt
.
ParacrossTx
r
.
TxHash
=
string
(
tx
.
Hash
())
r
.
TxHash
=
common
.
ToHex
(
tx
.
Hash
())
set
.
KV
=
append
(
set
.
KV
,
&
types
.
KeyValue
{
Key
:
calcLocalTxKey
(
g
.
Status
.
Title
,
g
.
Status
.
Height
,
tx
.
From
()),
Value
:
types
.
Encode
(
&
r
)})
}
}
...
...
plugin/dapp/token/commands/utils.go
View file @
7d9726f6
...
...
@@ -34,7 +34,7 @@ func CreateRawTx(cmd *cobra.Command, to string, amount float64, note string, isW
transfer
.
Value
=
v
transfer
.
Ty
=
tokenty
.
ActionTransfer
}
else
{
v
:=
&
tokenty
.
TokenAction_Withdraw
{
Withdraw
:
&
types
.
AssetsWithdraw
{
Cointoken
:
tokenSymbol
,
Amount
:
amountInt64
,
Note
:
[]
byte
(
note
)}}
v
:=
&
tokenty
.
TokenAction_Withdraw
{
Withdraw
:
&
types
.
AssetsWithdraw
{
Cointoken
:
tokenSymbol
,
Amount
:
amountInt64
,
Note
:
[]
byte
(
note
)
,
To
:
to
}}
transfer
.
Value
=
v
transfer
.
Ty
=
tokenty
.
ActionWithdraw
}
...
...
plugin/dapp/trade/executor/query.go
View file @
7d9726f6
...
...
@@ -614,6 +614,7 @@ func (t *trade) loadOrderFromKey(key []byte) *pty.ReplyTradeOrder {
return
nil
}
reply
.
TradedBoardlot
=
sellOrder
.
SoldBoardlot
reply
.
Status
=
sellOrder
.
Status
return
reply
}
else
if
strings
.
HasPrefix
(
string
(
key
),
buyIDPrefix
)
{
txHash
:=
strings
.
Replace
(
string
(
key
),
buyIDPrefix
,
"0x"
,
1
)
...
...
@@ -629,6 +630,7 @@ func (t *trade) loadOrderFromKey(key []byte) *pty.ReplyTradeOrder {
return
nil
}
reply
.
TradedBoardlot
=
buyOrder
.
BoughtBoardlot
reply
.
Status
=
buyOrder
.
Status
return
reply
}
txResult
,
err
:=
getTx
(
key
,
t
.
GetLocalDB
())
...
...
plugin/dapp/trade/executor/trade.go
View file @
7d9726f6
...
...
@@ -140,7 +140,7 @@ func genSaveBuyLimitKv(buyOrder *pty.BuyLimitOrder) []*types.KeyValue {
kv
=
saveBuyLimitOrderKeyValue
(
kv
,
buyOrder
,
status
)
if
pty
.
TradeOrderStatusBoughtOut
==
status
||
pty
.
TradeOrderStatusBuyRevoked
==
status
{
tradelog
.
Debug
(
"trade saveBuyLimit "
,
"remove old status with Buyid"
,
buyOrder
.
BuyID
)
kv
=
deleteBuyLimitKeyValue
(
kv
,
buyOrder
,
pty
.
TradeOrderStatusOn
Sale
)
kv
=
deleteBuyLimitKeyValue
(
kv
,
buyOrder
,
pty
.
TradeOrderStatusOn
Buy
)
}
return
kv
}
...
...
vendor/github.com/33cn/chain33/.travis.yml
View file @
7d9726f6
...
...
@@ -6,9 +6,9 @@ dist: xenial
notifications
:
email
:
false
jobs
:
matrix
:
include
:
-
stag
e
:
check_fmt
-
nam
e
:
check_fmt
sudo
:
require
go
:
-
"
1.9"
...
...
@@ -23,13 +23,13 @@ jobs:
-
make checkgofmt && make fmt_go
-
make linter
-
stag
e
:
unit-test
-
nam
e
:
unit-test
go
:
"
1.9.x"
install
:
skip
script
:
-
make test
-
stag
e
:
coverage
-
nam
e
:
coverage
if
:
branch = master
go
:
-
"
1.9.x"
...
...
@@ -41,7 +41,7 @@ jobs:
after_success
:
-
bash <(curl -s https://codecov.io/bash)
-
stag
e
:
deploy
-
nam
e
:
deploy
sudo
:
required
services
:
-
docker
...
...
vendor/github.com/33cn/chain33/common/db/db.go
View file @
7d9726f6
...
...
@@ -8,7 +8,6 @@ package db
import
(
"bytes"
"errors"
"fmt"
"github.com/33cn/chain33/types"
...
...
@@ -16,7 +15,7 @@ import (
)
//ErrNotFoundInDb error
var
ErrNotFoundInDb
=
errors
.
New
(
"ErrNotFoundInDb"
)
var
ErrNotFoundInDb
=
types
.
ErrNotFound
//Lister 列表接口
type
Lister
interface
{
...
...
vendor/github.com/33cn/chain33/common/db/db_test.go
View file @
7d9726f6
...
...
@@ -11,6 +11,7 @@ import (
"fmt"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
...
...
@@ -234,3 +235,26 @@ func testDBIteratorDel(t *testing.T, db DB) {
batch
.
Write
()
}
}
func
testLevelDBBatch
(
t
*
testing
.
T
,
db
DB
)
{
batch
:=
db
.
NewBatch
(
false
)
batch
.
Set
([]
byte
(
"hello"
),
[]
byte
(
"world"
))
err
:=
batch
.
Write
()
assert
.
Nil
(
t
,
err
)
v
,
err
:=
db
.
Get
([]
byte
(
"hello"
))
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
v
,
[]
byte
(
"world"
))
//set and del
batch
.
Set
([]
byte
(
"hello1"
),
[]
byte
(
"world"
))
batch
.
Set
([]
byte
(
"hello2"
),
[]
byte
(
"world"
))
batch
.
Set
([]
byte
(
"hello3"
),
[]
byte
(
"world"
))
batch
.
Set
([]
byte
(
"hello4"
),
[]
byte
(
"world"
))
batch
.
Set
([]
byte
(
"hello5"
),
[]
byte
(
"world"
))
batch
.
Delete
([]
byte
(
"hello1"
))
err
=
batch
.
Write
()
assert
.
Nil
(
t
,
err
)
v
,
err
=
db
.
Get
([]
byte
(
"hello1"
))
assert
.
Equal
(
t
,
err
,
types
.
ErrNotFound
)
assert
.
Nil
(
t
,
v
)
}
vendor/github.com/33cn/chain33/common/db/go_level_db_test.go
View file @
7d9726f6
...
...
@@ -43,6 +43,18 @@ func TestGoLevelDBIteratorDel(t *testing.T) {
testDBIteratorDel
(
t
,
leveldb
)
}
func
TestLevelDBBatch
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"goleveldb"
)
require
.
NoError
(
t
,
err
)
t
.
Log
(
dir
)
leveldb
,
err
:=
NewGoLevelDB
(
"goleveldb"
,
dir
,
128
)
require
.
NoError
(
t
,
err
)
defer
leveldb
.
Close
()
testLevelDBBatch
(
t
,
leveldb
)
}
// leveldb边界测试
func
TestGoLevelDBBoundary
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"goleveldb"
)
...
...
vendor/github.com/33cn/chain33/common/db/list_helper.go
View file @
7d9726f6
...
...
@@ -55,7 +55,6 @@ func (db *ListHelper) List(prefix, key []byte, count, direction int32) (values [
return
db
.
IteratorScanFromFirst
(
prefix
,
count
)
}
return
db
.
IteratorScanFromLast
(
prefix
,
count
)
}
if
count
==
1
&&
direction
==
ListSeek
{
it
:=
db
.
db
.
Iterator
(
prefix
,
nil
,
true
)
...
...
vendor/github.com/33cn/chain33/common/db/table/count.go
0 → 100644
View file @
7d9726f6
// 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
table
import
(
"math"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
)
//Count 计数器
type
Count
struct
{
prefix
string
name
string
kvdb
db
.
KV
num
int64
keydata
[]
byte
}
//NewCount 创建一个计数器
func
NewCount
(
prefix
string
,
name
string
,
kvdb
db
.
KV
)
*
Count
{
keydata
:=
[]
byte
(
prefix
+
"#"
+
name
)
return
&
Count
{
prefix
:
prefix
,
name
:
name
,
kvdb
:
kvdb
,
keydata
:
keydata
,
num
:
math
.
MinInt64
,
}
}
func
(
c
*
Count
)
getKey
()
[]
byte
{
return
c
.
keydata
}
//Save 保存kv
func
(
c
*
Count
)
Save
()
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
{
if
c
.
num
==
math
.
MinInt64
{
return
nil
,
nil
}
var
i
types
.
Int64
i
.
Data
=
c
.
num
item
:=
&
types
.
KeyValue
{
Key
:
c
.
getKey
(),
Value
:
types
.
Encode
(
&
i
)}
kvs
=
append
(
kvs
,
item
)
return
}
//Get count
func
(
c
*
Count
)
Get
()
(
int64
,
error
)
{
if
c
.
num
==
math
.
MinInt64
{
data
,
err
:=
c
.
kvdb
.
Get
(
c
.
getKey
())
if
err
==
types
.
ErrNotFound
{
c
.
num
=
0
}
else
if
err
!=
nil
{
return
0
,
err
}
var
num
types
.
Int64
err
=
types
.
Decode
(
data
,
&
num
)
if
err
!=
nil
{
return
0
,
err
}
c
.
num
=
num
.
Data
}
return
c
.
num
,
nil
}
//Inc 增加1
func
(
c
*
Count
)
Inc
()
(
num
int64
,
err
error
)
{
c
.
num
,
err
=
c
.
Get
()
if
err
!=
nil
{
return
0
,
err
}
c
.
num
++
return
c
.
num
,
nil
}
//Dec 减少1
func
(
c
*
Count
)
Dec
()
(
num
int64
,
err
error
)
{
c
.
num
,
err
=
c
.
Get
()
if
err
!=
nil
{
return
0
,
err
}
c
.
num
--
return
c
.
num
,
nil
}
//Set 这个操作要谨慎使用
func
(
c
*
Count
)
Set
(
i
int64
)
{
c
.
num
=
i
}
vendor/github.com/33cn/chain33/common/db/table/count_test.go
0 → 100644
View file @
7d9726f6
// 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
table
import
(
"testing"
"github.com/stretchr/testify/assert"
)
func
TestCount
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
count
:=
NewCount
(
"prefix"
,
"name#hello"
,
kvdb
)
count
.
Inc
()
count
.
Dec
()
count
.
Inc
()
i
,
err
:=
count
.
Get
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
i
,
int64
(
1
))
kvs
,
err
:=
count
.
Save
()
assert
.
Nil
(
t
,
err
)
setKV
(
leveldb
,
kvs
)
count
=
NewCount
(
"prefix"
,
"name#hello"
,
kvdb
)
i
,
err
=
count
.
Get
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
i
,
int64
(
1
))
count
.
Set
(
2
)
i
,
err
=
count
.
Get
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
i
,
int64
(
2
))
}
vendor/github.com/33cn/chain33/common/db/table/error.go
0 → 100644
View file @
7d9726f6
// 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
table
import
"errors"
//table 中的错误处理
var
(
ErrEmptyPrimaryKey
=
errors
.
New
(
"ErrEmptyPrimaryKey"
)
ErrPrimaryKey
=
errors
.
New
(
"ErrPrimaryKey"
)
ErrIndexKey
=
errors
.
New
(
"ErrIndexKey"
)
ErrTooManyIndex
=
errors
.
New
(
"ErrTooManyIndex"
)
ErrTablePrefixOrTableName
=
errors
.
New
(
"ErrTablePrefixOrTableName"
)
ErrDupPrimaryKey
=
errors
.
New
(
"ErrDupPrimaryKey"
)
)
vendor/github.com/33cn/chain33/common/db/table/query.go
0 → 100644
View file @
7d9726f6
// 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
table
import
(
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
)
//Query 列表查询结构
type
Query
struct
{
table
*
Table
kvdb
db
.
KVDB
}
//ListIndex 根据索引查询列表
//index 用哪个index
//prefix 必须要符合的前缀, 可以为空
//primaryKey 开始查询的位置(不包含数据本身)
//count 最多取的数量
//direction 方向
func
(
query
*
Query
)
ListIndex
(
indexName
string
,
prefix
[]
byte
,
primaryKey
[]
byte
,
count
,
direction
int32
)
(
rows
[]
*
Row
,
err
error
)
{
if
indexName
==
""
{
return
query
.
ListPrimary
(
prefix
,
primaryKey
,
count
,
direction
)
}
p
:=
query
.
table
.
indexPrefix
(
indexName
)
var
k
[]
byte
if
len
(
primaryKey
)
>
0
{
row
,
err
:=
query
.
table
.
GetData
(
primaryKey
)
if
err
!=
nil
{
return
nil
,
err
}
key
,
err
:=
query
.
table
.
index
(
row
,
indexName
)
if
err
!=
nil
{
return
nil
,
err
}
//如果存在prefix
if
prefix
!=
nil
{
p2
:=
commonPrefix
(
prefix
,
key
)
if
len
(
p2
)
!=
len
(
prefix
)
{
return
nil
,
types
.
ErrNotFound
}
p
=
append
(
p
,
p2
...
)
}
k
=
query
.
table
.
getIndexKey
(
indexName
,
key
,
row
.
Primary
)
}
else
{
//这个情况下 k == nil
p
=
append
(
p
,
prefix
...
)
}
values
,
err
:=
query
.
kvdb
.
List
(
p
,
k
,
count
,
direction
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
value
:=
range
values
{
row
,
err
:=
query
.
table
.
GetData
(
value
)
if
err
!=
nil
{
return
nil
,
err
}
rows
=
append
(
rows
,
row
)
}
return
rows
,
nil
}
//ListPrimary list primary data
func
(
query
*
Query
)
ListPrimary
(
prefix
[]
byte
,
primaryKey
[]
byte
,
count
,
direction
int32
)
(
rows
[]
*
Row
,
err
error
)
{
p
:=
query
.
table
.
primaryPrefix
()
var
k
[]
byte
if
primaryKey
!=
nil
{
if
prefix
!=
nil
{
p2
:=
commonPrefix
(
prefix
,
primaryKey
)
if
len
(
p2
)
!=
len
(
prefix
)
{
return
nil
,
types
.
ErrNotFound
}
p
=
append
(
p
,
p2
...
)
}
k
=
append
(
p
,
primaryKey
...
)
}
else
{
p
=
append
(
p
,
prefix
...
)
}
values
,
err
:=
query
.
kvdb
.
List
(
p
,
k
,
count
,
direction
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
value
:=
range
values
{
row
,
err
:=
query
.
table
.
getRow
(
value
)
if
err
!=
nil
{
return
nil
,
err
}
rows
=
append
(
rows
,
row
)
}
return
rows
,
nil
}
func
commonPrefix
(
key1
,
key2
[]
byte
)
[]
byte
{
l1
:=
len
(
key1
)
l2
:=
len
(
key2
)
l
:=
min
(
l1
,
l2
)
for
i
:=
0
;
i
<
l
;
i
++
{
if
key1
[
i
]
!=
key2
[
i
]
{
return
key1
[
:
i
]
}
}
return
key1
[
0
:
l
]
}
func
min
(
a
,
b
int
)
int
{
if
a
<
b
{
return
a
}
return
b
}
vendor/github.com/33cn/chain33/common/db/table/table.go
0 → 100644
View file @
7d9726f6
// 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 table 实现一个基于kv的关系型数据库的表格功能
package
table
import
(
"bytes"
"encoding/binary"
"fmt"
"strings"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
)
//设计结构:
/*
核心: 平衡
save:
数据保存:
tableprefix + tablename + Primary -> data
index:
tableprefix + tablemetaname + index + primary -> primary
read:
list by Primary -> 直接读出数据
list by index
根据index 先计算要读出的 primary list
从数据table读出数据(根据 primary key)
del:
利用 primaryKey + index 删除所有的 数据 和 索引
*/
//指出是 添加 还是 删除 行
//primary key auto 的del 需要指定 primary key
const
(
None
=
iota
Add
Del
)
//meta key
const
meta
=
"#m#"
const
data
=
"#d#"
//RowMeta 定义行的操作
type
RowMeta
interface
{
CreateRow
()
*
Row
SetPayload
(
types
.
Message
)
error
Get
(
key
string
)
([]
byte
,
error
)
}
//Row 行操作
type
Row
struct
{
Ty
int
Primary
[]
byte
Data
types
.
Message
}
func
encodeInt64
(
p
int64
)
([]
byte
,
error
)
{
buf
:=
new
(
bytes
.
Buffer
)
err
:=
binary
.
Write
(
buf
,
binary
.
LittleEndian
,
p
)
if
err
!=
nil
{
return
nil
,
err
}
return
buf
.
Bytes
(),
nil
}
func
decodeInt64
(
p
[]
byte
)
(
int64
,
error
)
{
buf
:=
bytes
.
NewBuffer
(
p
)
var
i
int64
err
:=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
i
)
if
err
!=
nil
{
return
0
,
err
}
return
i
,
nil
}
//Encode row
func
(
row
*
Row
)
Encode
()
([]
byte
,
error
)
{
b
,
err
:=
encodeInt64
(
int64
(
len
(
row
.
Primary
)))
if
err
!=
nil
{
return
nil
,
err
}
b
=
append
(
b
,
row
.
Primary
...
)
b
=
append
(
b
,
types
.
Encode
(
row
.
Data
)
...
)
return
b
,
nil
}
//DecodeRow from data
func
DecodeRow
(
data
[]
byte
)
([]
byte
,
[]
byte
,
error
)
{
if
len
(
data
)
<=
8
{
return
nil
,
nil
,
types
.
ErrDecode
}
l
,
err
:=
decodeInt64
(
data
[
:
8
])
if
err
!=
nil
{
return
nil
,
nil
,
err
}
if
len
(
data
)
<
int
(
l
)
+
8
{
return
nil
,
nil
,
types
.
ErrDecode
}
return
data
[
8
:
int
(
l
)
+
8
],
data
[
int
(
l
)
+
8
:
],
nil
}
//Table 定一个表格, 并且添加 primary key, index key
type
Table
struct
{
meta
RowMeta
rows
[]
*
Row
rowmap
map
[
string
]
*
Row
kvdb
db
.
KV
opt
*
Option
autoinc
*
Count
dataprefix
string
metaprefix
string
}
//Option table 的选项
type
Option
struct
{
Prefix
string
Name
string
Primary
string
Index
[]
string
}
//NewTable 新建一个表格
//primary 可以为: auto, 由系统自动创建
//index 可以为nil
func
NewTable
(
rowmeta
RowMeta
,
kvdb
db
.
KV
,
opt
*
Option
)
(
*
Table
,
error
)
{
if
len
(
opt
.
Index
)
>
16
{
return
nil
,
ErrTooManyIndex
}
for
_
,
index
:=
range
opt
.
Index
{
if
strings
.
Contains
(
index
,
"#"
)
{
return
nil
,
ErrIndexKey
}
}
if
opt
.
Primary
==
""
{
opt
.
Primary
=
"auto"
}
if
_
,
err
:=
getPrimaryKey
(
rowmeta
,
opt
.
Primary
);
err
!=
nil
{
return
nil
,
err
}
//不允许有#
if
strings
.
Contains
(
opt
.
Prefix
,
"#"
)
||
strings
.
Contains
(
opt
.
Name
,
"#"
)
{
return
nil
,
ErrTablePrefixOrTableName
}
dataprefix
:=
opt
.
Prefix
+
"#"
+
opt
.
Name
+
data
metaprefix
:=
opt
.
Prefix
+
"#"
+
opt
.
Name
+
meta
count
:=
NewCount
(
opt
.
Prefix
,
opt
.
Name
+
"#autoinc#"
,
kvdb
)
return
&
Table
{
meta
:
rowmeta
,
kvdb
:
kvdb
,
rowmap
:
make
(
map
[
string
]
*
Row
),
opt
:
opt
,
autoinc
:
count
,
dataprefix
:
dataprefix
,
metaprefix
:
metaprefix
},
nil
}
func
getPrimaryKey
(
meta
RowMeta
,
primary
string
)
([]
byte
,
error
)
{
if
primary
==
""
{
return
nil
,
ErrEmptyPrimaryKey
}
if
strings
.
Contains
(
primary
,
"#"
)
{
return
nil
,
ErrPrimaryKey
}
if
primary
!=
"auto"
{
key
,
err
:=
meta
.
Get
(
primary
)
return
key
,
err
}
return
nil
,
nil
}
func
(
table
*
Table
)
addRowCache
(
row
*
Row
)
{
table
.
rowmap
[
string
(
row
.
Primary
)]
=
row
table
.
rows
=
append
(
table
.
rows
,
row
)
}
func
(
table
*
Table
)
findRow
(
primary
[]
byte
)
(
*
Row
,
error
)
{
if
row
,
ok
:=
table
.
rowmap
[
string
(
primary
)];
ok
{
return
row
,
nil
}
return
table
.
GetData
(
primary
)
}
func
(
table
*
Table
)
checkIndex
(
data
types
.
Message
)
error
{
err
:=
table
.
meta
.
SetPayload
(
data
)
if
err
!=
nil
{
return
err
}
if
_
,
err
:=
getPrimaryKey
(
table
.
meta
,
table
.
opt
.
Primary
);
err
!=
nil
{
return
err
}
for
i
:=
0
;
i
<
len
(
table
.
opt
.
Index
);
i
++
{
_
,
err
:=
table
.
meta
.
Get
(
table
.
opt
.
Index
[
i
])
if
err
!=
nil
{
return
err
}
}
return
nil
}
func
(
table
*
Table
)
getPrimaryAuto
()
([]
byte
,
error
)
{
i
,
err
:=
table
.
autoinc
.
Inc
()
if
err
!=
nil
{
return
nil
,
err
}
return
[]
byte
(
pad
(
i
)),
nil
}
//primaryKey 获取主键
//1. auto 的情况下,只能自增。
//2. 没有auto的情况下从数据中取
func
(
table
*
Table
)
primaryKey
(
data
types
.
Message
)
(
primaryKey
[]
byte
,
err
error
)
{
if
table
.
opt
.
Primary
==
"auto"
{
primaryKey
,
err
=
table
.
getPrimaryAuto
()
if
err
!=
nil
{
return
nil
,
err
}
}
else
{
primaryKey
,
err
=
table
.
getPrimaryFromData
(
data
)
}
return
}
func
(
table
*
Table
)
getPrimaryFromData
(
data
types
.
Message
)
(
primaryKey
[]
byte
,
err
error
)
{
err
=
table
.
meta
.
SetPayload
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
primaryKey
,
err
=
getPrimaryKey
(
table
.
meta
,
table
.
opt
.
Primary
)
if
err
!=
nil
{
return
nil
,
err
}
return
}
//Replace 如果有重复的,那么替换
func
(
table
*
Table
)
Replace
(
data
types
.
Message
)
error
{
if
err
:=
table
.
checkIndex
(
data
);
err
!=
nil
{
return
err
}
primaryKey
,
err
:=
table
.
primaryKey
(
data
)
if
err
!=
nil
{
return
err
}
//如果是auto的情况,一定是添加
if
table
.
opt
.
Primary
==
"auto"
{
table
.
addRowCache
(
&
Row
{
Data
:
data
,
Primary
:
primaryKey
,
Ty
:
Add
})
return
nil
}
//如果没有找到行, 那么添加
row
,
err
:=
table
.
findRow
(
primaryKey
)
if
err
==
types
.
ErrNotFound
{
table
.
addRowCache
(
&
Row
{
Data
:
data
,
Primary
:
primaryKey
,
Ty
:
Add
})
return
nil
}
//更新数据
delrow
:=
*
row
delrow
.
Ty
=
Del
//update 是一个del 和 update 的组合
table
.
addRowCache
(
&
delrow
)
table
.
addRowCache
(
&
Row
{
Data
:
data
,
Primary
:
primaryKey
,
Ty
:
Add
})
return
nil
}
//Add 在表格中添加一行
func
(
table
*
Table
)
Add
(
data
types
.
Message
)
error
{
if
err
:=
table
.
checkIndex
(
data
);
err
!=
nil
{
return
err
}
primaryKey
,
err
:=
table
.
primaryKey
(
data
)
if
err
!=
nil
{
return
err
}
//find in cache + db
_
,
err
=
table
.
findRow
(
primaryKey
)
if
err
!=
types
.
ErrNotFound
{
return
ErrDupPrimaryKey
}
//检查cache中是否有重复,有重复也返回错误
table
.
addRowCache
(
&
Row
{
Data
:
data
,
Primary
:
primaryKey
,
Ty
:
Add
})
return
nil
}
//Update 更新数据库
func
(
table
*
Table
)
Update
(
primaryKey
[]
byte
,
newdata
types
.
Message
)
(
err
error
)
{
if
err
:=
table
.
checkIndex
(
newdata
);
err
!=
nil
{
return
err
}
p1
,
err
:=
table
.
getPrimaryFromData
(
newdata
)
if
err
!=
nil
{
return
err
}
if
!
bytes
.
Equal
(
p1
,
primaryKey
)
{
return
types
.
ErrInvalidParam
}
row
,
err
:=
table
.
findRow
(
primaryKey
)
//查询发生错误
if
err
!=
nil
{
return
err
}
delrow
:=
*
row
delrow
.
Ty
=
Del
//update 是一个del 和 update 的组合
table
.
addRowCache
(
&
delrow
)
table
.
addRowCache
(
&
Row
{
Data
:
newdata
,
Primary
:
primaryKey
,
Ty
:
Add
})
return
nil
}
//Del 在表格中删除一行(包括删除索引)
func
(
table
*
Table
)
Del
(
primaryKey
[]
byte
)
error
{
row
,
err
:=
table
.
findRow
(
primaryKey
)
if
err
!=
nil
{
return
err
}
delrow
:=
*
row
delrow
.
Ty
=
Del
table
.
addRowCache
(
&
delrow
)
return
nil
}
//getDataKey data key 构造
func
(
table
*
Table
)
getDataKey
(
primaryKey
[]
byte
)
[]
byte
{
return
append
([]
byte
(
table
.
dataprefix
),
primaryKey
...
)
}
//GetIndexKey data key 构造
func
(
table
*
Table
)
getIndexKey
(
indexName
string
,
index
,
primaryKey
[]
byte
)
[]
byte
{
key
:=
table
.
indexPrefix
(
indexName
)
key
=
append
(
key
,
index
...
)
key
=
append
(
key
,
[]
byte
(
"#"
)
...
)
key
=
append
(
key
,
primaryKey
...
)
return
key
}
func
(
table
*
Table
)
primaryPrefix
()
[]
byte
{
return
[]
byte
(
table
.
dataprefix
)
}
func
(
table
*
Table
)
indexPrefix
(
indexName
string
)
[]
byte
{
key
:=
append
([]
byte
(
table
.
metaprefix
),
[]
byte
(
indexName
+
"#"
)
...
)
return
key
}
func
(
table
*
Table
)
index
(
row
*
Row
,
indexName
string
)
([]
byte
,
error
)
{
err
:=
table
.
meta
.
SetPayload
(
row
.
Data
)
if
err
!=
nil
{
return
nil
,
err
}
return
table
.
meta
.
Get
(
indexName
)
}
func
(
table
*
Table
)
getData
(
primaryKey
[]
byte
)
([]
byte
,
error
)
{
key
:=
table
.
getDataKey
(
primaryKey
)
value
,
err
:=
table
.
kvdb
.
Get
(
key
)
if
err
!=
nil
{
return
nil
,
err
}
return
value
,
nil
}
//GetData 根据主键获取数据
func
(
table
*
Table
)
GetData
(
primaryKey
[]
byte
)
(
*
Row
,
error
)
{
value
,
err
:=
table
.
getData
(
primaryKey
)
if
err
!=
nil
{
return
nil
,
err
}
return
table
.
getRow
(
value
)
}
func
(
table
*
Table
)
getRow
(
value
[]
byte
)
(
*
Row
,
error
)
{
primary
,
data
,
err
:=
DecodeRow
(
value
)
if
err
!=
nil
{
return
nil
,
err
}
row
:=
table
.
meta
.
CreateRow
()
row
.
Primary
=
primary
err
=
types
.
Decode
(
data
,
row
.
Data
)
if
err
!=
nil
{
return
nil
,
err
}
return
row
,
nil
}
//Save 保存表格
func
(
table
*
Table
)
Save
()
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
{
for
_
,
row
:=
range
table
.
rows
{
kvlist
,
err
:=
table
.
saveRow
(
row
)
if
err
!=
nil
{
return
nil
,
err
}
kvs
=
append
(
kvs
,
kvlist
...
)
}
kvlist
,
err
:=
table
.
autoinc
.
Save
()
if
err
!=
nil
{
return
nil
,
err
}
kvs
=
append
(
kvs
,
kvlist
...
)
//del cache
table
.
rowmap
=
make
(
map
[
string
]
*
Row
)
table
.
rows
=
nil
return
kvs
,
nil
}
func
pad
(
i
int64
)
string
{
return
fmt
.
Sprintf
(
"%020d"
,
i
)
}
func
(
table
*
Table
)
saveRow
(
row
*
Row
)
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
{
if
row
.
Ty
==
Del
{
return
table
.
delRow
(
row
)
}
return
table
.
addRow
(
row
)
}
func
(
table
*
Table
)
delRow
(
row
*
Row
)
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
{
deldata
:=
&
types
.
KeyValue
{
Key
:
table
.
getDataKey
(
row
.
Primary
)}
kvs
=
append
(
kvs
,
deldata
)
for
_
,
index
:=
range
table
.
opt
.
Index
{
indexkey
,
err
:=
table
.
index
(
row
,
index
)
if
err
!=
nil
{
return
nil
,
err
}
delindex
:=
&
types
.
KeyValue
{
Key
:
table
.
getIndexKey
(
index
,
indexkey
,
row
.
Primary
)}
kvs
=
append
(
kvs
,
delindex
)
}
return
kvs
,
nil
}
func
(
table
*
Table
)
addRow
(
row
*
Row
)
(
kvs
[]
*
types
.
KeyValue
,
err
error
)
{
data
,
err
:=
row
.
Encode
()
if
err
!=
nil
{
return
nil
,
err
}
adddata
:=
&
types
.
KeyValue
{
Key
:
table
.
getDataKey
(
row
.
Primary
),
Value
:
data
}
kvs
=
append
(
kvs
,
adddata
)
for
_
,
index
:=
range
table
.
opt
.
Index
{
indexkey
,
err
:=
table
.
index
(
row
,
index
)
if
err
!=
nil
{
return
nil
,
err
}
addindex
:=
&
types
.
KeyValue
{
Key
:
table
.
getIndexKey
(
index
,
indexkey
,
row
.
Primary
),
Value
:
row
.
Primary
}
kvs
=
append
(
kvs
,
addindex
)
}
return
kvs
,
nil
}
//GetQuery 获取查询结构
func
(
table
*
Table
)
GetQuery
(
kvdb
db
.
KVDB
)
*
Query
{
return
&
Query
{
table
:
table
,
kvdb
:
kvdb
}
}
vendor/github.com/33cn/chain33/common/db/table/table_test.go
0 → 100644
View file @
7d9726f6
// 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
table
import
(
"bytes"
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
)
func
TestTransactinList
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
opt
:=
&
Option
{
Prefix
:
"prefix"
,
Name
:
"name"
,
Primary
:
"Hash"
,
Index
:
[]
string
{
"From"
,
"To"
},
}
table
,
err
:=
NewTable
(
NewTransactionRow
(),
kvdb
,
opt
)
assert
.
Nil
(
t
,
err
)
addr1
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx1
)
assert
.
Nil
(
t
,
err
)
tx2
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx2
)
assert
.
Nil
(
t
,
err
)
addr2
,
priv
:=
util
.
Genaddress
()
tx3
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx3
)
assert
.
Nil
(
t
,
err
)
tx4
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx4
)
assert
.
Nil
(
t
,
err
)
//添加一个无效的类型
err
=
table
.
Add
(
nil
)
assert
.
Equal
(
t
,
types
.
ErrTypeAsset
,
err
)
kvs
,
err
:=
table
.
Save
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
kvs
),
12
)
//save to database
setKV
(
leveldb
,
kvs
)
//测试查询
query
:=
table
.
GetQuery
(
kvdb
)
rows
,
err
:=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
),
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
if
bytes
.
Compare
(
tx1
.
Hash
(),
tx2
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx1
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx2
,
rows
[
1
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx1
,
rows
[
1
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx2
,
rows
[
0
]
.
Data
))
}
//prefix full
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
),
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
if
bytes
.
Compare
(
tx3
.
Hash
(),
tx4
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
1
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
1
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
}
//prefix part
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
if
bytes
.
Compare
(
tx3
.
Hash
(),
tx4
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
1
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
1
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
}
//count
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
nil
,
1
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
if
bytes
.
Compare
(
tx3
.
Hash
(),
tx4
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
}
primary
:=
rows
[
0
]
.
Primary
//primary
rows
,
err
=
query
.
ListIndex
(
"From"
,
nil
,
primary
,
1
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
if
bytes
.
Compare
(
tx3
.
Hash
(),
tx4
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
}
//prefix + primary
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
primary
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
if
bytes
.
Compare
(
tx3
.
Hash
(),
tx4
.
Hash
())
>
0
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
}
else
{
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
}
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
[
0
:
10
]),
primary
,
0
,
0
)
assert
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
assert
.
Equal
(
t
,
0
,
len
(
rows
))
//ListPrimary all
rows
,
err
=
query
.
ListPrimary
(
nil
,
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
4
,
len
(
rows
))
primary
=
rows
[
0
]
.
Primary
rows
,
err
=
query
.
ListPrimary
(
primary
[
0
:
10
],
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
rows
,
err
=
query
.
ListPrimary
(
nil
,
primary
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
3
,
len
(
rows
))
}
func
TestTransactinListAuto
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
opt
:=
&
Option
{
Prefix
:
"prefix"
,
Name
:
"name"
,
Primary
:
""
,
Index
:
[]
string
{
"From"
,
"To"
},
}
table
,
err
:=
NewTable
(
NewTransactionRow
(),
kvdb
,
opt
)
assert
.
Nil
(
t
,
err
)
addr1
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx1
)
assert
.
Nil
(
t
,
err
)
tx2
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx2
)
assert
.
Nil
(
t
,
err
)
addr2
,
priv
:=
util
.
Genaddress
()
tx3
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx3
)
assert
.
Nil
(
t
,
err
)
tx4
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx4
)
assert
.
Nil
(
t
,
err
)
//添加一个无效的类型
err
=
table
.
Add
(
nil
)
assert
.
Equal
(
t
,
types
.
ErrTypeAsset
,
err
)
kvs
,
err
:=
table
.
Save
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
kvs
),
13
)
//save to database
setKV
(
leveldb
,
kvs
)
//测试查询
query
:=
table
.
GetQuery
(
kvdb
)
rows
,
err
:=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
),
nil
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx1
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx2
,
rows
[
1
]
.
Data
))
//prefix full
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
),
nil
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
1
]
.
Data
))
//prefix part
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
nil
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
2
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
1
]
.
Data
))
//count
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
nil
,
1
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx3
,
rows
[
0
]
.
Data
))
primary
:=
rows
[
0
]
.
Primary
//primary
rows
,
err
=
query
.
ListIndex
(
"From"
,
nil
,
primary
,
1
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
//prefix + primary
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr2
[
0
:
10
]),
primary
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
assert
.
Equal
(
t
,
true
,
proto
.
Equal
(
tx4
,
rows
[
0
]
.
Data
))
rows
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
[
0
:
10
]),
primary
,
0
,
db
.
ListASC
)
assert
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
assert
.
Equal
(
t
,
0
,
len
(
rows
))
//ListPrimary all
rows
,
err
=
query
.
ListPrimary
(
nil
,
nil
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
4
,
len
(
rows
))
primary
=
rows
[
0
]
.
Primary
rows
,
err
=
query
.
ListPrimary
(
primary
,
nil
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
rows
))
rows
,
err
=
query
.
ListPrimary
(
nil
,
primary
,
0
,
db
.
ListASC
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
3
,
len
(
rows
))
}
func
mergeDup
(
kvs
[]
*
types
.
KeyValue
)
(
kvset
[]
*
types
.
KeyValue
)
{
maplist
:=
make
(
map
[
string
]
*
types
.
KeyValue
)
for
_
,
kv
:=
range
kvs
{
if
item
,
ok
:=
maplist
[
string
(
kv
.
Key
)];
ok
{
item
.
Value
=
kv
.
Value
//更新item 的value
}
else
{
maplist
[
string
(
kv
.
Key
)]
=
kv
kvset
=
append
(
kvset
,
kv
)
}
}
return
kvset
}
func
setKV
(
kvdb
db
.
DB
,
kvs
[]
*
types
.
KeyValue
)
{
batch
:=
kvdb
.
NewBatch
(
true
)
for
i
:=
0
;
i
<
len
(
kvs
);
i
++
{
if
kvs
[
i
]
.
Value
==
nil
{
batch
.
Delete
(
kvs
[
i
]
.
Key
)
continue
}
batch
.
Set
(
kvs
[
i
]
.
Key
,
kvs
[
i
]
.
Value
)
}
err
:=
batch
.
Write
()
if
err
!=
nil
{
panic
(
err
)
}
}
func
printKV
(
kvs
[]
*
types
.
KeyValue
)
{
for
i
:=
0
;
i
<
len
(
kvs
);
i
++
{
fmt
.
Println
(
"KV"
,
i
,
string
(
kvs
[
i
]
.
Key
),
common
.
ToHex
(
kvs
[
i
]
.
Value
))
}
}
func
TestRow
(
t
*
testing
.
T
)
{
rowmeta
:=
NewTransactionRow
()
row
:=
rowmeta
.
CreateRow
()
_
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
row
.
Data
=
tx1
row
.
Primary
=
tx1
.
Hash
()
data
,
err
:=
row
.
Encode
()
assert
.
Nil
(
t
,
err
)
primary
,
protodata
,
err
:=
DecodeRow
(
data
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
primary
,
row
.
Primary
)
var
tx
types
.
Transaction
err
=
types
.
Decode
(
protodata
,
&
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
proto
.
Equal
(
&
tx
,
tx1
),
true
)
}
func
TestDel
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
opt
:=
&
Option
{
Prefix
:
"prefix"
,
Name
:
"name"
,
Primary
:
"Hash"
,
Index
:
[]
string
{
"From"
,
"To"
},
}
table
,
err
:=
NewTable
(
NewTransactionRow
(),
kvdb
,
opt
)
assert
.
Nil
(
t
,
err
)
addr1
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx1
)
assert
.
Nil
(
t
,
err
)
_
,
priv
=
util
.
Genaddress
()
tx2
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx2
)
assert
.
Nil
(
t
,
err
)
//删除掉一个
err
=
table
.
Del
(
tx1
.
Hash
())
assert
.
Nil
(
t
,
err
)
//save 然后从列表中读取
kvs
,
err
:=
table
.
Save
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
kvs
),
9
)
//save to database
setKV
(
leveldb
,
kvs
)
//printKV(kvs)
query
:=
table
.
GetQuery
(
kvdb
)
rows
,
err
:=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
[
0
:
10
]),
nil
,
0
,
0
)
assert
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
assert
.
Equal
(
t
,
0
,
len
(
rows
))
}
func
printAllKey
(
db
db
.
DB
)
{
it
:=
db
.
Iterator
(
nil
,
nil
,
false
)
defer
it
.
Close
()
for
it
.
Rewind
();
it
.
Valid
();
it
.
Next
()
{
fmt
.
Println
(
"db.allkey"
,
string
(
it
.
Key
()))
}
}
func
TestUpdate
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
opt
:=
&
Option
{
Prefix
:
"prefix"
,
Name
:
"name"
,
Primary
:
"Hash"
,
Index
:
[]
string
{
"From"
,
"To"
},
}
table
,
err
:=
NewTable
(
NewTransactionRow
(),
kvdb
,
opt
)
assert
.
Nil
(
t
,
err
)
_
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx1
)
assert
.
Nil
(
t
,
err
)
err
=
table
.
Update
([]
byte
(
"hello"
),
tx1
)
assert
.
Equal
(
t
,
err
,
types
.
ErrInvalidParam
)
tx1
.
Signature
=
nil
err
=
table
.
Update
(
tx1
.
Hash
(),
tx1
)
assert
.
Nil
(
t
,
err
)
kvs
,
err
:=
table
.
Save
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
kvs
),
9
)
//save to database
setKV
(
leveldb
,
kvs
)
query
:=
table
.
GetQuery
(
kvdb
)
rows
,
err
:=
query
.
ListIndex
(
"From"
,
[]
byte
(
tx1
.
From
()),
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
rows
[
0
]
.
Data
.
(
*
types
.
Transaction
)
.
From
(),
tx1
.
From
())
}
func
TestReplace
(
t
*
testing
.
T
)
{
dir
,
leveldb
,
kvdb
:=
getdb
()
defer
dbclose
(
dir
,
leveldb
)
opt
:=
&
Option
{
Prefix
:
"prefix"
,
Name
:
"name"
,
Primary
:
"Hash"
,
Index
:
[]
string
{
"From"
,
"To"
},
}
table
,
err
:=
NewTable
(
NewTransactionRow
(),
kvdb
,
opt
)
assert
.
Nil
(
t
,
err
)
addr1
,
priv
:=
util
.
Genaddress
()
tx1
:=
util
.
CreateNoneTx
(
priv
)
err
=
table
.
Add
(
tx1
)
assert
.
Nil
(
t
,
err
)
err
=
table
.
Add
(
tx1
)
assert
.
Equal
(
t
,
err
,
ErrDupPrimaryKey
)
//不改变hash,改变签名
tx1
.
Signature
=
nil
err
=
table
.
Replace
(
tx1
)
assert
.
Nil
(
t
,
err
)
//save 然后从列表中读取
kvs
,
err
:=
table
.
Save
()
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
len
(
kvs
),
9
)
//save to database
setKV
(
leveldb
,
kvs
)
query
:=
table
.
GetQuery
(
kvdb
)
_
,
err
=
query
.
ListIndex
(
"From"
,
[]
byte
(
addr1
[
0
:
10
]),
nil
,
0
,
0
)
assert
.
Equal
(
t
,
err
,
types
.
ErrNotFound
)
rows
,
err
:=
query
.
ListIndex
(
"From"
,
[]
byte
(
tx1
.
From
()),
nil
,
0
,
0
)
assert
.
Nil
(
t
,
err
)
assert
.
Equal
(
t
,
rows
[
0
]
.
Data
.
(
*
types
.
Transaction
)
.
From
(),
tx1
.
From
())
}
type
TransactionRow
struct
{
*
types
.
Transaction
}
func
NewTransactionRow
()
*
TransactionRow
{
return
&
TransactionRow
{
Transaction
:
&
types
.
Transaction
{}}
}
func
(
tx
*
TransactionRow
)
CreateRow
()
*
Row
{
return
&
Row
{
Data
:
&
types
.
Transaction
{}}
}
func
(
tx
*
TransactionRow
)
SetPayload
(
data
types
.
Message
)
error
{
if
txdata
,
ok
:=
data
.
(
*
types
.
Transaction
);
ok
{
tx
.
Transaction
=
txdata
return
nil
}
return
types
.
ErrTypeAsset
}
func
(
tx
*
TransactionRow
)
Get
(
key
string
)
([]
byte
,
error
)
{
if
key
==
"Hash"
{
return
tx
.
Hash
(),
nil
}
else
if
key
==
"From"
{
return
[]
byte
(
tx
.
From
()),
nil
}
else
if
key
==
"To"
{
return
[]
byte
(
tx
.
To
),
nil
}
return
nil
,
types
.
ErrNotFound
}
func
getdb
()
(
string
,
db
.
DB
,
db
.
KVDB
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"goleveldb"
)
if
err
!=
nil
{
panic
(
err
)
}
leveldb
,
err
:=
db
.
NewGoLevelDB
(
"goleveldb"
,
dir
,
128
)
if
err
!=
nil
{
panic
(
err
)
}
return
dir
,
leveldb
,
db
.
NewKVDB
(
leveldb
)
}
func
dbclose
(
dir
string
,
dbm
db
.
DB
)
{
os
.
RemoveAll
(
dir
)
dbm
.
Close
()
}
vendor/github.com/33cn/chain33/system/dapp/commands/types/utils.go
View file @
7d9726f6
...
...
@@ -105,7 +105,7 @@ func CreateRawTx(cmd *cobra.Command, to string, amount float64, note string, isW
transfer
.
Ty
=
cty
.
CoinsActionTransfer
}
}
else
{
v
:=
&
cty
.
CoinsAction_Withdraw
{
Withdraw
:
&
types
.
AssetsWithdraw
{
Amount
:
amountInt64
,
Note
:
[]
byte
(
note
),
ExecName
:
execName
}}
v
:=
&
cty
.
CoinsAction_Withdraw
{
Withdraw
:
&
types
.
AssetsWithdraw
{
Amount
:
amountInt64
,
Note
:
[]
byte
(
note
),
ExecName
:
execName
,
To
:
to
}}
transfer
.
Value
=
v
transfer
.
Ty
=
cty
.
CoinsActionWithdraw
}
...
...
vendor/github.com/33cn/chain33/system/mempool/eventprocess.go
View file @
7d9726f6
...
...
@@ -97,7 +97,7 @@ func (mem *Mempool) eventProcess() {
func
(
mem
*
Mempool
)
eventTx
(
msg
queue
.
Message
)
{
if
!
mem
.
getSync
()
{
msg
.
Reply
(
mem
.
client
.
NewMessage
(
""
,
types
.
EventReply
,
&
types
.
Reply
{
Msg
:
[]
byte
(
types
.
ErrNotSync
.
Error
())}))
mlog
.
Error
(
"wrong tx"
,
"err"
,
types
.
ErrNotSync
.
Error
())
mlog
.
Debug
(
"wrong tx"
,
"err"
,
types
.
ErrNotSync
.
Error
())
}
else
{
checkedMsg
:=
mem
.
checkTxs
(
msg
)
select
{
...
...
vendor/github.com/33cn/chain33/util/util.go
View file @
7d9726f6
...
...
@@ -111,7 +111,9 @@ func CreateTxWithExecer(priv crypto.PrivKey, execer string) *types.Transaction {
tx
:=
&
types
.
Transaction
{
Execer
:
[]
byte
(
execer
),
Payload
:
[]
byte
(
"none"
)}
tx
.
To
=
address
.
ExecAddress
(
execer
)
tx
,
_
=
types
.
FormatTx
(
execer
,
tx
)
tx
.
Sign
(
types
.
SECP256K1
,
priv
)
if
priv
!=
nil
{
tx
.
Sign
(
types
.
SECP256K1
,
priv
)
}
return
tx
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment