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
75d588eb
Commit
75d588eb
authored
Feb 05, 2021
by
jiangpeng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dapp/vote:add test
parent
ae0dcb83
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1166 additions
and
68 deletions
+1166
-68
action.go
plugin/dapp/vote/executor/action.go
+5
-2
checktx.go
plugin/dapp/vote/executor/checktx.go
+3
-0
checktx_test.go
plugin/dapp/vote/executor/checktx_test.go
+256
-0
errors.go
plugin/dapp/vote/executor/errors.go
+1
-0
exec_local.go
plugin/dapp/vote/executor/exec_local.go
+12
-5
exec_test.go
plugin/dapp/vote/executor/exec_test.go
+140
-0
execlocal_test.go
plugin/dapp/vote/executor/execlocal_test.go
+270
-0
query.go
plugin/dapp/vote/executor/query.go
+3
-3
query_test.go
plugin/dapp/vote/executor/query_test.go
+202
-0
util_test.go
plugin/dapp/vote/executor/util_test.go
+207
-0
vote.proto
plugin/dapp/vote/proto/vote.proto
+1
-0
vote.pb.go
plugin/dapp/vote/types/vote.pb.go
+66
-58
No files found.
plugin/dapp/vote/executor/action.go
View file @
75d588eb
...
@@ -173,15 +173,18 @@ func (a *action) commitVote(commit *vty.CommitVote) (*types.Receipt, error) {
...
@@ -173,15 +173,18 @@ func (a *action) commitVote(commit *vty.CommitVote) (*types.Receipt, error) {
elog
.
Error
(
"vote exec commitVote"
,
"txHash"
,
a
.
txHash
,
"get group err"
,
err
)
elog
.
Error
(
"vote exec commitVote"
,
"txHash"
,
a
.
txHash
,
"get group err"
,
err
)
return
nil
,
errStateDBGet
return
nil
,
errStateDBGet
}
}
var
voteWeight
uint32
for
_
,
member
:=
range
group
.
Members
{
for
_
,
member
:=
range
group
.
Members
{
if
member
.
Addr
==
a
.
fromAddr
{
if
member
.
Addr
==
a
.
fromAddr
{
vote
.
VoteOptions
[
commit
.
OptionIndex
]
.
Score
+
=
member
.
VoteWeight
vote
Weight
=
member
.
VoteWeight
}
}
}
}
vote
.
VoteOptions
[
commit
.
OptionIndex
]
.
Score
+=
voteWeight
info
:=
&
vty
.
CommitInfo
{
Addr
:
a
.
fromAddr
}
info
:=
&
vty
.
CommitInfo
{
Addr
:
a
.
fromAddr
}
vote
.
CommitInfos
=
append
(
vote
.
CommitInfos
,
info
)
vote
.
CommitInfos
=
append
(
vote
.
CommitInfos
,
info
)
voteValue
:=
types
.
Encode
(
vote
)
voteValue
:=
types
.
Encode
(
vote
)
//提交的哈希和权重等信息不记录到statedb中
info
.
VoteWeight
=
voteWeight
info
.
TxHash
=
hex
.
EncodeToString
(
a
.
txHash
)
info
.
TxHash
=
hex
.
EncodeToString
(
a
.
txHash
)
receipt
.
KV
=
append
(
receipt
.
KV
,
&
types
.
KeyValue
{
Key
:
formatStateIDKey
(
vote
.
ID
),
Value
:
voteValue
})
receipt
.
KV
=
append
(
receipt
.
KV
,
&
types
.
KeyValue
{
Key
:
formatStateIDKey
(
vote
.
ID
),
Value
:
voteValue
})
receipt
.
Logs
=
append
(
receipt
.
Logs
,
&
types
.
ReceiptLog
{
Ty
:
vty
.
TyCommitVoteLog
,
Log
:
types
.
Encode
(
info
)})
receipt
.
Logs
=
append
(
receipt
.
Logs
,
&
types
.
ReceiptLog
{
Ty
:
vty
.
TyCommitVoteLog
,
Log
:
types
.
Encode
(
info
)})
...
...
plugin/dapp/vote/executor/checktx.go
View file @
75d588eb
...
@@ -152,6 +152,9 @@ func (v *vote) checkCommitVote(commit *vty.CommitVote, tx *types.Transaction, in
...
@@ -152,6 +152,9 @@ func (v *vote) checkCommitVote(commit *vty.CommitVote, tx *types.Transaction, in
return
err
return
err
}
}
if
voteInfo
.
BeginTimestamp
>
action
.
blockTime
{
return
errVoteNotStarted
}
if
voteInfo
.
EndTimestamp
<=
action
.
blockTime
{
if
voteInfo
.
EndTimestamp
<=
action
.
blockTime
{
return
errVoteAlreadyFinished
return
errVoteAlreadyFinished
}
}
...
...
plugin/dapp/vote/executor/checktx_test.go
0 → 100644
View file @
75d588eb
package
executor
import
(
"testing"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
vty
"github.com/33cn/plugin/plugin/dapp/vote/types"
)
func
TestVote_CheckTx_CreateGroup
(
t
*
testing
.
T
)
{
tcArr
:=
[]
*
testcase
{{
index
:
1
,
payload
:
&
vty
.
CreateGroup
{},
expectCheckErr
:
errEmptyName
,
},
{
index
:
2
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{}}},
expectCheckErr
:
errNilMember
,
},
{
index
:
3
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
],
},
{
Addr
:
testAddrs
[
0
],
}},
},
expectCheckErr
:
errDuplicateMember
,
},
{
index
:
4
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Admins
:
[]
string
{
testAddrs
[
0
],
testAddrs
[
0
]}},
expectCheckErr
:
errDuplicateAdmin
,
},
{
index
:
5
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
func
TestVote_CheckTx_UpdateGroup
(
t
*
testing
.
T
)
{
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
execType
:
testTypeExecLocal
,
},
{
index
:
1
,
payload
:
&
vty
.
UpdateGroup
{},
expectCheckErr
:
errGroupNotExist
,
},
{
index
:
2
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
},
priv
:
privKeys
[
1
],
expectCheckErr
:
errAddrPermissionDenied
,
},
{
index
:
3
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
RemoveAdmins
:
testAddrs
[
:
]},
expectCheckErr
:
errAddrPermissionDenied
,
},
{
index
:
4
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddMembers
:
[]
*
vty
.
GroupMember
{{
Addr
:
"errAddr"
}}},
expectCheckErr
:
types
.
ErrInvalidAddress
,
},
{
index
:
5
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddAdmins
:
[]
string
{
"errAddr"
}},
expectCheckErr
:
types
.
ErrInvalidAddress
,
},
{
index
:
6
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddAdmins
:
[]
string
{
address
.
MultiSignAddress
(
privKeys
[
0
]
.
PubKey
()
.
Bytes
())}},
expectCheckErr
:
types
.
ErrInvalidAddress
,
},
{
index
:
7
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddAdmins
:
[]
string
{
testAddrs
[
1
]}},
},
}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
func
TestVote_CheckTx_CreateVote
(
t
*
testing
.
T
)
{
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
execType
:
testTypeExecLocal
,
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{},
expectCheckErr
:
errEmptyName
,
},
{
index
:
2
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
},
expectCheckErr
:
errGroupNotExist
,
},
{
index
:
3
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
},
priv
:
privKeys
[
1
],
expectCheckErr
:
errAddrPermissionDenied
,
},
{
index
:
4
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
},
expectCheckErr
:
errInvalidVoteTime
,
},
{
index
:
5
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
BeginTimestamp
:
testBlockTime
+
1
,
EndTimestamp
:
testBlockTime
+
1
,
},
expectCheckErr
:
errInvalidVoteTime
,
},
{
index
:
6
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
EndTimestamp
:
testBlockTime
+
1
,
},
expectCheckErr
:
errInvalidVoteOption
,
},
{
index
:
7
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
EndTimestamp
:
testBlockTime
+
1
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
},
},
}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
func
TestVote_CheckTx_CommitVote
(
t
*
testing
.
T
)
{
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
vote2
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
7
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
]}}},
execType
:
testTypeExecLocal
,
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
EndTimestamp
:
testBlockTime
+
1
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
},
execType
:
testTypeExecLocal
,
},
{
index
:
2
,
payload
:
&
vty
.
CommitVote
{},
expectCheckErr
:
errVoteNotExist
,
},
{
index
:
3
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
,
OptionIndex
:
10
},
expectCheckErr
:
errInvalidOptionIndex
,
},
{
index
:
4
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
priv
:
privKeys
[
1
],
expectCheckErr
:
errAddrPermissionDenied
,
},
{
index
:
5
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
execType
:
testTypeExecLocal
,
},
{
index
:
6
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
expectCheckErr
:
errAddrAlreadyVoted
,
},
{
index
:
7
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
BeginTimestamp
:
testBlockTime
+
1
,
EndTimestamp
:
testBlockTime
+
2
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
},
execType
:
testTypeExecLocal
,
},
{
index
:
8
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
vote2
},
expectCheckErr
:
errVoteNotStarted
,
}}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
func
TestVote_CheckTx_CloseVote
(
t
*
testing
.
T
)
{
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
]}}},
execType
:
testTypeExecLocal
,
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
EndTimestamp
:
testBlockTime
+
1
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
},
execType
:
testTypeExecLocal
,
},
{
index
:
2
,
payload
:
&
vty
.
CloseVote
{},
expectCheckErr
:
errVoteNotExist
,
},
{
index
:
3
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
priv
:
privKeys
[
1
],
expectCheckErr
:
errAddrPermissionDenied
,
},
{
index
:
4
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
execType
:
testTypeExecLocal
,
},
{
index
:
5
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
expectCheckErr
:
errVoteAlreadyClosed
,
},
}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
func
TestVote_CheckTx_UpdateMember
(
t
*
testing
.
T
)
{
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
UpdateMember
{},
expectCheckErr
:
errEmptyName
,
},
{
index
:
1
,
payload
:
&
vty
.
UpdateMember
{
Name
:
"test"
},
},
}
testExec
(
t
,
nil
,
testTypeCheckTx
,
tcArr
,
privKeys
[
0
])
}
plugin/dapp/vote/executor/errors.go
View file @
75d588eb
...
@@ -21,6 +21,7 @@ var (
...
@@ -21,6 +21,7 @@ var (
errAddrAlreadyVoted
=
errors
.
New
(
"errAddrAlreadyVoted"
)
errAddrAlreadyVoted
=
errors
.
New
(
"errAddrAlreadyVoted"
)
errInvalidGroupMember
=
errors
.
New
(
"errInvalidGroupMember"
)
errInvalidGroupMember
=
errors
.
New
(
"errInvalidGroupMember"
)
errVoteAlreadyFinished
=
errors
.
New
(
"errVoteAlreadyFinished"
)
errVoteAlreadyFinished
=
errors
.
New
(
"errVoteAlreadyFinished"
)
errVoteNotStarted
=
errors
.
New
(
"errVoteNotStarted"
)
errVoteAlreadyClosed
=
errors
.
New
(
"errVoteAlreadyClosed"
)
errVoteAlreadyClosed
=
errors
.
New
(
"errVoteAlreadyClosed"
)
errAddrPermissionDenied
=
errors
.
New
(
"errAddrPermissionDenied"
)
errAddrPermissionDenied
=
errors
.
New
(
"errAddrPermissionDenied"
)
)
)
plugin/dapp/vote/executor/exec_local.go
View file @
75d588eb
...
@@ -25,7 +25,9 @@ func (v *vote) ExecLocal_CreateGroup(payload *vty.CreateGroup, tx *types.Transac
...
@@ -25,7 +25,9 @@ func (v *vote) ExecLocal_CreateGroup(payload *vty.CreateGroup, tx *types.Transac
addAddrs
:=
make
([]
string
,
0
)
addAddrs
:=
make
([]
string
,
0
)
addAddrs
=
append
(
addAddrs
,
groupInfo
.
Admins
...
)
addAddrs
=
append
(
addAddrs
,
groupInfo
.
Admins
...
)
for
_
,
member
:=
range
groupInfo
.
Members
{
for
_
,
member
:=
range
groupInfo
.
Members
{
addAddrs
=
append
(
addAddrs
,
member
.
Addr
)
if
!
checkSliceItemExist
(
member
.
Addr
,
groupInfo
.
Admins
)
{
addAddrs
=
append
(
addAddrs
,
member
.
Addr
)
}
}
}
kvs
,
err
=
v
.
addGroupMember
(
groupInfo
.
GetID
(),
addAddrs
)
kvs
,
err
=
v
.
addGroupMember
(
groupInfo
.
GetID
(),
addAddrs
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -47,12 +49,14 @@ func (v *vote) ExecLocal_UpdateGroup(update *vty.UpdateGroup, tx *types.Transact
...
@@ -47,12 +49,14 @@ func (v *vote) ExecLocal_UpdateGroup(update *vty.UpdateGroup, tx *types.Transact
return
nil
,
err
return
nil
,
err
}
}
dbSet
.
KV
=
kvs
dbSet
.
KV
=
kvs
removeAddrs
:=
append
(
update
.
RemoveAdmins
,
update
.
RemoveMembers
...
)
removeAddrs
:=
make
([]
string
,
0
)
//仍然为管理员或群成员之一,不删除groupID索引
//仍然为管理员或群成员之一,不删除groupID索引
for
i
,
addr
:=
range
removeAddrs
{
tempAddrs
:=
append
(
update
.
RemoveAdmins
,
update
.
RemoveMembers
...
)
for
_
,
addr
:=
range
tempAddrs
{
if
checkMemberExist
(
addr
,
groupInfo
.
Members
)
||
checkSliceItemExist
(
addr
,
groupInfo
.
Admins
)
{
if
checkMemberExist
(
addr
,
groupInfo
.
Members
)
||
checkSliceItemExist
(
addr
,
groupInfo
.
Admins
)
{
removeAddrs
=
append
(
removeAddrs
[
:
i
],
removeAddrs
[
i
+
1
:
]
...
)
continue
}
}
removeAddrs
=
append
(
removeAddrs
,
addr
)
}
}
kvs
,
err
=
v
.
removeGroupMember
(
groupInfo
.
GetID
(),
removeAddrs
)
kvs
,
err
=
v
.
removeGroupMember
(
groupInfo
.
GetID
(),
removeAddrs
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -63,7 +67,9 @@ func (v *vote) ExecLocal_UpdateGroup(update *vty.UpdateGroup, tx *types.Transact
...
@@ -63,7 +67,9 @@ func (v *vote) ExecLocal_UpdateGroup(update *vty.UpdateGroup, tx *types.Transact
addAddrs
:=
make
([]
string
,
0
)
addAddrs
:=
make
([]
string
,
0
)
addAddrs
=
append
(
addAddrs
,
update
.
AddAdmins
...
)
addAddrs
=
append
(
addAddrs
,
update
.
AddAdmins
...
)
for
_
,
member
:=
range
update
.
AddMembers
{
for
_
,
member
:=
range
update
.
AddMembers
{
addAddrs
=
append
(
addAddrs
,
member
.
Addr
)
if
!
checkSliceItemExist
(
member
.
Addr
,
update
.
AddAdmins
)
{
addAddrs
=
append
(
addAddrs
,
member
.
Addr
)
}
}
}
kvs
,
err
=
v
.
addGroupMember
(
groupInfo
.
GetID
(),
addAddrs
)
kvs
,
err
=
v
.
addGroupMember
(
groupInfo
.
GetID
(),
addAddrs
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -112,6 +118,7 @@ func (v *vote) ExecLocal_CommitVote(payload *vty.CommitVote, tx *types.Transacti
...
@@ -112,6 +118,7 @@ func (v *vote) ExecLocal_CommitVote(payload *vty.CommitVote, tx *types.Transacti
return
nil
,
err
return
nil
,
err
}
}
voteInfo
,
_
:=
row
.
Data
.
(
*
vty
.
VoteInfo
)
voteInfo
,
_
:=
row
.
Data
.
(
*
vty
.
VoteInfo
)
voteInfo
.
VoteOptions
[
payload
.
OptionIndex
]
.
Score
+=
commitInfo
.
VoteWeight
voteInfo
.
CommitInfos
=
append
(
voteInfo
.
CommitInfos
,
commitInfo
)
voteInfo
.
CommitInfos
=
append
(
voteInfo
.
CommitInfos
,
commitInfo
)
dbSet
.
KV
,
err
=
v
.
updateAndSaveTable
(
table
.
Replace
,
table
.
Save
,
voteInfo
,
tx
,
vty
.
NameCommitVoteAction
,
"vote"
)
dbSet
.
KV
,
err
=
v
.
updateAndSaveTable
(
table
.
Replace
,
table
.
Save
,
voteInfo
,
tx
,
vty
.
NameCommitVoteAction
,
"vote"
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
plugin/dapp/vote/executor/exec_test.go
0 → 100644
View file @
75d588eb
package
executor
import
(
"testing"
"github.com/33cn/chain33/system/dapp"
vty
"github.com/33cn/plugin/plugin/dapp/vote/types"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/stretchr/testify/require"
)
const
(
testTypeCheckTx
=
iota
+
1
testTypeExec
testTypeExecLocal
testTypeExecDelLocal
)
func
testExec
(
t
*
testing
.
T
,
mock
*
testExecMock
,
testExecType
int
,
tcArr
[]
*
testcase
,
priv
crypto
.
PrivKey
)
{
if
mock
==
nil
{
mock
=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
}
exec
:=
mock
.
exec
for
i
,
tc
:=
range
tcArr
{
signPriv
:=
priv
if
tc
.
priv
!=
nil
{
signPriv
=
tc
.
priv
}
tx
,
err
:=
createTx
(
mock
,
tc
.
payload
,
signPriv
)
require
.
NoErrorf
(
t
,
err
,
"createTxErr, testIndex=%d"
,
tc
.
index
)
if
err
!=
nil
{
continue
}
err
=
exec
.
CheckTx
(
tx
,
i
)
require
.
Equalf
(
t
,
tc
.
expectCheckErr
,
err
,
"checkTx err index %d"
,
tc
.
index
)
execType
:=
testExecType
if
tc
.
execType
>
0
{
execType
=
tc
.
execType
}
if
execType
==
testTypeCheckTx
{
continue
}
recp
,
err
:=
exec
.
Exec
(
tx
,
i
)
recpData
:=
&
types
.
ReceiptData
{
Ty
:
recp
.
GetTy
(),
Logs
:
recp
.
GetLogs
(),
}
if
err
==
nil
&&
len
(
recp
.
GetKV
())
>
0
{
util
.
SaveKVList
(
mock
.
stateDB
,
recp
.
KV
)
}
require
.
Equalf
(
t
,
tc
.
expectExecErr
,
err
,
"execTx err index %d"
,
tc
.
index
)
if
execType
==
testTypeExec
{
continue
}
kvSet
,
err
:=
exec
.
ExecLocal
(
tx
,
recpData
,
i
)
for
_
,
kv
:=
range
kvSet
.
GetKV
()
{
err
:=
mock
.
localDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
require
.
Nil
(
t
,
err
)
}
require
.
Equalf
(
t
,
tc
.
expectExecLocalErr
,
err
,
"execLocalTx err index %d"
,
tc
.
index
)
if
execType
==
testTypeExecLocal
{
continue
}
kvSet
,
err
=
exec
.
ExecDelLocal
(
tx
,
recpData
,
i
)
for
_
,
kv
:=
range
kvSet
.
GetKV
()
{
err
:=
mock
.
localDB
.
Set
(
kv
.
Key
,
kv
.
Value
)
require
.
Nil
(
t
,
err
)
}
require
.
Equalf
(
t
,
tc
.
expectExecDelErr
,
err
,
"execDelLocalTx err index %d"
,
tc
.
index
)
}
}
func
TestVote_Exec
(
t
*
testing
.
T
)
{
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
]}}},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"vote"
,
GroupID
:
groupID
,
EndTimestamp
:
testBlockTime
+
1
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
},
},
{
index
:
2
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
RemoveAdmins
:
testAddrs
,
AddAdmins
:
[]
string
{
testAddrs
[
1
]}},
},
{
index
:
3
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
},
{
index
:
4
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddAdmins
:
[]
string
{
testAddrs
[
0
]}},
expectCheckErr
:
errAddrPermissionDenied
,
execType
:
testTypeCheckTx
,
},
{
index
:
5
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
RemoveAdmins
:
testAddrs
,
AddAdmins
:
[]
string
{
testAddrs
[
0
]}},
priv
:
privKeys
[
1
],
},
{
index
:
6
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
AddMembers
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
1
]}},
RemoveMembers
:
testAddrs
},
},
{
index
:
7
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
expectCheckErr
:
errAddrPermissionDenied
,
execType
:
testTypeCheckTx
,
},
{
index
:
8
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
priv
:
privKeys
[
1
],
},
{
index
:
9
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
},
{
index
:
10
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
execType
:
testTypeCheckTx
,
expectCheckErr
:
errVoteAlreadyClosed
,
},
{
index
:
11
,
payload
:
&
vty
.
UpdateMember
{
Name
:
"testName"
},
},
}
testExec
(
t
,
nil
,
testTypeExec
,
tcArr
,
privKeys
[
0
])
}
plugin/dapp/vote/executor/execlocal_test.go
0 → 100644
View file @
75d588eb
package
executor
import
(
"testing"
tab
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
vty
"github.com/33cn/plugin/plugin/dapp/vote/types"
"github.com/stretchr/testify/require"
)
type
tableCase
struct
{
index
int
key
[]
byte
expectGetErr
error
expectData
types
.
Message
}
func
testTableData
(
t
*
testing
.
T
,
table
*
tab
.
Table
,
tcArr
[]
*
tableCase
,
msg
string
)
{
for
_
,
tc
:=
range
tcArr
{
row
,
err
:=
table
.
GetData
(
tc
.
key
)
require
.
Equalf
(
t
,
tc
.
expectGetErr
,
err
,
msg
+
",index=%d"
,
tc
.
index
)
if
err
!=
nil
{
continue
}
require
.
Equalf
(
t
,
tc
.
expectData
.
String
(),
row
.
Data
.
String
(),
msg
+
",index=%d"
,
tc
.
index
)
}
}
func
TestVote_ExecLocal_CreateGroup
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
groupID2
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
members1
:=
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
1
],
VoteWeight
:
1
}}
members2
:=
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
2
],
VoteWeight
:
1
}}
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
members1
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
members2
},
},
}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newMemberTable
(
mock
.
exec
.
GetLocalDB
())
tcArr1
:=
[]
*
tableCase
{{
index
:
0
,
key
:
[]
byte
(
testAddrs
[
0
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
0
],
GroupIDs
:
[]
string
{
groupID
,
groupID2
}},
},
{
index
:
1
,
key
:
[]
byte
(
testAddrs
[
1
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
1
],
GroupIDs
:
[]
string
{
groupID
}},
},
{
index
:
2
,
key
:
[]
byte
(
testAddrs
[
2
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
2
],
GroupIDs
:
[]
string
{
groupID2
}},
},
{
index
:
3
,
key
:
[]
byte
(
"addr"
),
expectGetErr
:
types
.
ErrNotFound
,
}}
testTableData
(
t
,
table
,
tcArr1
,
"check member groupIDs"
)
table
=
newGroupTable
(
mock
.
exec
.
GetLocalDB
())
tcArr1
=
[]
*
tableCase
{{
index
:
0
,
key
:
[]
byte
(
groupID
),
expectData
:
&
vty
.
GroupInfo
{
ID
:
groupID
,
Name
:
"test"
,
MemberNum
:
1
,
Admins
:
[]
string
{
testAddrs
[
0
]},
Creator
:
testAddrs
[
0
],
Members
:
members1
},
},
{
index
:
1
,
key
:
[]
byte
(
groupID2
),
expectData
:
&
vty
.
GroupInfo
{
ID
:
groupID2
,
Name
:
"test"
,
MemberNum
:
1
,
Admins
:
[]
string
{
testAddrs
[
0
]},
Creator
:
testAddrs
[
0
],
Members
:
members2
},
}}
testTableData
(
t
,
table
,
tcArr1
,
"check groupInfo"
)
}
func
TestVote_ExecLocal_UpdateGroup
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
members
:=
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
2
],
VoteWeight
:
1
}}
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
RemoveAdmins
:
[]
string
{
testAddrs
[
0
]},
AddAdmins
:
[]
string
{
testAddrs
[
1
]}},
},
{
index
:
2
,
priv
:
privKeys
[
1
],
payload
:
&
vty
.
UpdateGroup
{
GroupID
:
groupID
,
RemoveMembers
:
testAddrs
,
AddMembers
:
members
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newMemberTable
(
mock
.
exec
.
GetLocalDB
())
tcArr1
:=
[]
*
tableCase
{{
index
:
0
,
key
:
[]
byte
(
testAddrs
[
0
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
0
]},
},
{
index
:
1
,
key
:
[]
byte
(
testAddrs
[
1
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
1
],
GroupIDs
:
[]
string
{
groupID
}},
},
{
index
:
2
,
key
:
[]
byte
(
testAddrs
[
2
]),
expectData
:
&
vty
.
MemberInfo
{
Addr
:
testAddrs
[
2
],
GroupIDs
:
[]
string
{
groupID
}},
}}
testTableData
(
t
,
table
,
tcArr1
,
"check member groupIDs"
)
table
=
newGroupTable
(
mock
.
exec
.
GetLocalDB
())
expectInfo
:=
&
vty
.
GroupInfo
{
ID
:
groupID
,
Name
:
"test"
,
Admins
:
[]
string
{
testAddrs
[
1
]},
Members
:
members
,
MemberNum
:
1
,
Creator
:
testAddrs
[
0
]}
testTableData
(
t
,
table
,
[]
*
tableCase
{{
index
:
0
,
key
:
[]
byte
(
groupID
),
expectData
:
expectInfo
,
},
{
index
:
1
,
key
:
[]
byte
(
"testid"
),
expectGetErr
:
types
.
ErrNotFound
,
}},
"check group Info"
)
tx
:=
util
.
CreateNoneTx
(
mock
.
cfg
,
privKeys
[
0
])
group
,
err
:=
newAction
(
mock
.
exec
,
tx
,
0
)
.
getGroupInfo
(
groupID
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
group
.
String
(),
expectInfo
.
String
())
}
func
TestVote_ExecLocal_CreateVote
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
options
:=
[]
*
vty
.
VoteOption
{{
Option
:
"A"
},
{
Option
:
"B"
}}
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newVoteTable
(
mock
.
exec
.
GetLocalDB
())
expectVoteInfo
:=
&
vty
.
VoteInfo
{
Name
:
"test"
,
VoteOptions
:
options
,
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
,
GroupID
:
groupID
,
ID
:
voteID
,
Creator
:
testAddrs
[
0
],
}
testTableData
(
t
,
table
,
[]
*
tableCase
{{
index
:
0
,
key
:
[]
byte
(
voteID
),
expectData
:
expectVoteInfo
,
}},
"check vote Info"
)
table
=
newGroupTable
(
mock
.
exec
.
GetLocalDB
())
row
,
err
:=
table
.
GetData
([]
byte
(
groupID
))
require
.
Nil
(
t
,
err
)
info
,
_
:=
row
.
Data
.
(
*
vty
.
GroupInfo
)
require
.
Equal
(
t
,
uint32
(
1
),
info
.
VoteNum
)
tx
:=
util
.
CreateNoneTx
(
mock
.
cfg
,
privKeys
[
0
])
group
,
err
:=
newAction
(
mock
.
exec
,
tx
,
0
)
.
getGroupInfo
(
groupID
)
require
.
Nil
(
t
,
err
)
group
.
VoteNum
=
info
.
VoteNum
require
.
Equal
(
t
,
group
.
String
(),
info
.
String
())
}
func
TestVote_ExecLocal_CloseVote
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
},
},
{
index
:
2
,
payload
:
&
vty
.
CloseVote
{
VoteID
:
voteID
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newVoteTable
(
mock
.
exec
.
GetLocalDB
())
row
,
err
:=
table
.
GetData
([]
byte
(
voteID
))
require
.
Nil
(
t
,
err
)
info
,
_
:=
row
.
Data
.
(
*
vty
.
VoteInfo
)
require
.
Equal
(
t
,
uint32
(
voteStatusClosed
),
info
.
Status
)
tx
:=
util
.
CreateNoneTx
(
mock
.
cfg
,
privKeys
[
0
])
vote
,
err
:=
newAction
(
mock
.
exec
,
tx
,
0
)
.
getVoteInfo
(
voteID
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
vote
.
String
(),
info
.
String
())
}
func
TestVote_ExecLocal_CommitVote
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
members
:=
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
],
VoteWeight
:
1
}}
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
members
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
},
},
{
index
:
2
,
payload
:
&
vty
.
CommitVote
{
VoteID
:
voteID
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newVoteTable
(
mock
.
exec
.
GetLocalDB
())
row
,
err
:=
table
.
GetData
([]
byte
(
voteID
))
require
.
Nil
(
t
,
err
)
info
,
_
:=
row
.
Data
.
(
*
vty
.
VoteInfo
)
require
.
Equal
(
t
,
testAddrs
[
0
],
info
.
CommitInfos
[
0
]
.
Addr
)
require
.
Equal
(
t
,
uint32
(
1
),
info
.
VoteOptions
[
0
]
.
Score
)
tx
:=
util
.
CreateNoneTx
(
mock
.
cfg
,
privKeys
[
0
])
vote
,
err
:=
newAction
(
mock
.
exec
,
tx
,
0
)
.
getVoteInfo
(
voteID
)
require
.
Nil
(
t
,
err
)
vote
.
CommitInfos
[
0
]
.
TxHash
=
info
.
CommitInfos
[
0
]
.
TxHash
vote
.
CommitInfos
[
0
]
.
VoteWeight
=
info
.
CommitInfos
[
0
]
.
VoteWeight
require
.
Equal
(
t
,
vote
.
String
(),
info
.
String
())
}
func
TestVote_ExecDelLocal
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
execType
:
testTypeExecLocal
,
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
},
}}
testExec
(
t
,
mock
,
testTypeExecDelLocal
,
tcArr
,
privKeys
[
0
])
table
:=
newVoteTable
(
mock
.
exec
.
GetLocalDB
())
_
,
err
:=
table
.
GetData
([]
byte
(
voteID
))
require
.
Equal
(
t
,
types
.
ErrDecode
,
err
)
}
plugin/dapp/vote/executor/query.go
View file @
75d588eb
...
@@ -29,7 +29,7 @@ func (v *vote) getGroup(groupID string) (*vty.GroupInfo, error) {
...
@@ -29,7 +29,7 @@ func (v *vote) getGroup(groupID string) (*vty.GroupInfo, error) {
// Query_GroupInfo query group info
// Query_GroupInfo query group info
func
(
v
*
vote
)
Query_GetGroups
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
func
(
v
*
vote
)
Query_GetGroups
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
if
in
==
nil
{
if
len
(
in
.
GetItems
())
==
0
{
return
nil
,
types
.
ErrInvalidParam
return
nil
,
types
.
ErrInvalidParam
}
}
infos
:=
&
vty
.
GroupInfos
{
GroupList
:
make
([]
*
vty
.
GroupInfo
,
0
,
len
(
in
.
GetItems
()))}
infos
:=
&
vty
.
GroupInfos
{
GroupList
:
make
([]
*
vty
.
GroupInfo
,
0
,
len
(
in
.
GetItems
()))}
...
@@ -65,7 +65,7 @@ func (v *vote) getVote(voteID string) (*vty.VoteInfo, error) {
...
@@ -65,7 +65,7 @@ func (v *vote) getVote(voteID string) (*vty.VoteInfo, error) {
func
(
v
*
vote
)
Query_GetVotes
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
func
(
v
*
vote
)
Query_GetVotes
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
if
in
==
nil
{
if
len
(
in
.
GetItems
())
==
0
{
return
nil
,
types
.
ErrInvalidParam
return
nil
,
types
.
ErrInvalidParam
}
}
voteList
:=
make
([]
*
vty
.
VoteInfo
,
0
,
len
(
in
.
GetItems
()))
voteList
:=
make
([]
*
vty
.
VoteInfo
,
0
,
len
(
in
.
GetItems
()))
...
@@ -104,7 +104,7 @@ func (v *vote) getMember(addr string) (*vty.MemberInfo, error) {
...
@@ -104,7 +104,7 @@ func (v *vote) getMember(addr string) (*vty.MemberInfo, error) {
func
(
v
*
vote
)
Query_GetMembers
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
func
(
v
*
vote
)
Query_GetMembers
(
in
*
vty
.
ReqStrings
)
(
types
.
Message
,
error
)
{
if
in
==
nil
{
if
len
(
in
.
GetItems
())
==
0
{
return
nil
,
types
.
ErrInvalidParam
return
nil
,
types
.
ErrInvalidParam
}
}
infos
:=
&
vty
.
MemberInfos
{
MemberList
:
make
([]
*
vty
.
MemberInfo
,
0
,
len
(
in
.
GetItems
()))}
infos
:=
&
vty
.
MemberInfos
{
MemberList
:
make
([]
*
vty
.
MemberInfo
,
0
,
len
(
in
.
GetItems
()))}
...
...
plugin/dapp/vote/executor/query_test.go
0 → 100644
View file @
75d588eb
package
executor
import
(
"testing"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
vty
"github.com/33cn/plugin/plugin/dapp/vote/types"
"github.com/stretchr/testify/require"
)
func
TestVote_Query_GetGroups
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
groupID2
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
groupID3
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
2
))
groupIDs
:=
[]
string
{
groupID
,
groupID2
,
groupID3
,
"testid"
}
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"GetGroups"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
types
.
ErrInvalidParam
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
groupIDs
[
3
:
]}))
require
.
Equal
(
t
,
errInvalidGroupID
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
groupIDs
[
:
3
]}))
require
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
groupIDs
[
:
2
]}))
require
.
Equal
(
t
,
nil
,
err
)
groups
:=
data
.
(
*
vty
.
GroupInfos
)
require
.
Equal
(
t
,
2
,
len
(
groups
.
GroupList
))
require
.
Equal
(
t
,
groupID
,
groups
.
GroupList
[
0
]
.
ID
)
require
.
Equal
(
t
,
groupID2
,
groups
.
GroupList
[
1
]
.
ID
)
}
func
TestVote_Query_GetVotes
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
voteID
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
voteID2
:=
formatVoteID
(
dapp
.
HeightIndexStr
(
testHeight
,
2
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
testBlockTime
,
EndTimestamp
:
testBlockTime
+
1
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"GetVotes"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
types
.
ErrInvalidParam
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
voteID2
}}))
require
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
"voteid"
}}))
require
.
Equal
(
t
,
errInvalidVoteID
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
voteID
}}))
require
.
Equal
(
t
,
nil
,
err
)
vote
:=
data
.
(
*
vty
.
ReplyVoteList
)
require
.
Equal
(
t
,
voteID
,
vote
.
VoteList
[
0
]
.
ID
)
}
func
TestVote_Query_GetMembers
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
]}}},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"GetMembers"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
types
.
ErrInvalidParam
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
testAddrs
[
1
]}}))
require
.
Equal
(
t
,
types
.
ErrNotFound
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
"addr"
}}))
require
.
Equal
(
t
,
types
.
ErrInvalidAddress
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqStrings
{
Items
:
[]
string
{
testAddrs
[
0
]}}))
require
.
Equal
(
t
,
nil
,
err
)
members
:=
data
.
(
*
vty
.
MemberInfos
)
require
.
Equal
(
t
,
testAddrs
[
0
],
members
.
MemberList
[
0
]
.
Addr
)
require
.
Equal
(
t
,
[]
string
{
groupID
},
members
.
MemberList
[
0
]
.
GroupIDs
)
}
func
TestVote_Query_ListGroup
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
groupID2
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
1
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"ListGroup"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
nil
,
err
)
list
:=
data
.
(
*
vty
.
GroupInfos
)
require
.
Equal
(
t
,
2
,
len
(
list
.
GroupList
))
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqListItem
{
Count
:
1
,
Direction
:
1
}))
require
.
Equal
(
t
,
nil
,
err
)
list
=
data
.
(
*
vty
.
GroupInfos
)
require
.
Equal
(
t
,
1
,
len
(
list
.
GroupList
))
require
.
Equal
(
t
,
groupID
,
list
.
GroupList
[
0
]
.
ID
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqListItem
{
StartItemID
:
groupID2
}))
require
.
Equal
(
t
,
nil
,
err
)
list
=
data
.
(
*
vty
.
GroupInfos
)
require
.
Equal
(
t
,
1
,
len
(
list
.
GroupList
))
require
.
Equal
(
t
,
groupID
,
list
.
GroupList
[
0
]
.
ID
)
}
func
TestVote_Query_ListVote
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
now
:=
types
.
Now
()
.
Unix
()
+
1000
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
},
},
{
index
:
1
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
EndTimestamp
:
testBlockTime
+
1
},
},
{
index
:
2
,
payload
:
&
vty
.
CreateVote
{
Name
:
"test"
,
GroupID
:
groupID
,
VoteOptions
:
[]
string
{
"A"
,
"B"
},
BeginTimestamp
:
now
,
EndTimestamp
:
now
+
1
},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"ListVote"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
types
.
ErrInvalidParam
,
err
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqListVote
{
GroupID
:
groupID
,
ListReq
:
&
vty
.
ReqListItem
{}}))
require
.
Nil
(
t
,
err
)
list
:=
data
.
(
*
vty
.
ReplyVoteList
)
require
.
Equal
(
t
,
2
,
len
(
list
.
VoteList
))
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqListVote
{
GroupID
:
groupID
,
Status
:
voteStatusPending
,
ListReq
:
&
vty
.
ReqListItem
{}}))
require
.
Nil
(
t
,
err
)
list
=
data
.
(
*
vty
.
ReplyVoteList
)
require
.
Equal
(
t
,
1
,
len
(
list
.
VoteList
))
require
.
Equal
(
t
,
uint32
(
voteStatusPending
),
list
.
VoteList
[
0
]
.
Status
)
}
func
TestVote_Query_ListMember
(
t
*
testing
.
T
)
{
mock
:=
&
testExecMock
{}
mock
.
InitEnv
()
defer
mock
.
FreeEnv
()
groupID
:=
formatGroupID
(
dapp
.
HeightIndexStr
(
testHeight
,
0
))
tcArr
:=
[]
*
testcase
{{
index
:
0
,
payload
:
&
vty
.
CreateGroup
{
Name
:
"test"
,
Members
:
[]
*
vty
.
GroupMember
{{
Addr
:
testAddrs
[
0
]}}},
}}
testExec
(
t
,
mock
,
testTypeExecLocal
,
tcArr
,
privKeys
[
0
])
exec
:=
mock
.
exec
funcName
:=
"ListMember"
data
,
err
:=
exec
.
Query
(
funcName
,
nil
)
require
.
Equal
(
t
,
nil
,
err
)
list
:=
data
.
(
*
vty
.
MemberInfos
)
require
.
Equal
(
t
,
1
,
len
(
list
.
MemberList
))
require
.
Equal
(
t
,
testAddrs
[
0
],
list
.
MemberList
[
0
]
.
Addr
)
require
.
Equal
(
t
,
[]
string
{
groupID
},
list
.
MemberList
[
0
]
.
GroupIDs
)
data
,
err
=
exec
.
Query
(
funcName
,
types
.
Encode
(
&
vty
.
ReqListItem
{
StartItemID
:
"addr"
}))
require
.
Equal
(
t
,
nil
,
err
)
list
=
data
.
(
*
vty
.
MemberInfos
)
require
.
Equal
(
t
,
&
vty
.
MemberInfos
{},
list
)
}
plugin/dapp/vote/executor/util_test.go
0 → 100644
View file @
75d588eb
package
executor
import
(
"errors"
"testing"
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto"
dbm
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/queue"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
wcom
"github.com/33cn/chain33/wallet/common"
vty
"github.com/33cn/plugin/plugin/dapp/vote/types"
"github.com/stretchr/testify/require"
)
var
(
testHeight
=
int64
(
100
)
testBlockTime
=
int64
(
1539918074
)
// 测试的私钥
testPrivateKeys
=
[]
string
{
"0x8dea7332c7bb3e3b0ce542db41161fd021e3cfda9d7dabacf24f98f2dfd69558"
,
"0x920976ffe83b5a98f603b999681a0bc790d97e22ffc4e578a707c2234d55cc8a"
,
"0xb59f2b02781678356c231ad565f73699753a28fd3226f1082b513ebf6756c15c"
,
}
// 测试的地址
testAddrs
=
[]
string
{
"1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
,
"13cS5G1BDN2YfGudsxRxr7X25yu6ZdgxMU"
,
"1JSRSwp16NvXiTjYBYK9iUQ9wqp3sCxz2p"
,
}
// 测试的隐私公钥对
testPubkeyPairs
=
[]
string
{
"92fe6cfec2e19cd15f203f83b5d440ddb63d0cb71559f96dc81208d819fea85886b08f6e874fca15108d244b40f9086d8c03260d4b954a40dfb3cbe41ebc7389"
,
"6326126c968a93a546d8f67d623ad9729da0e3e4b47c328a273dfea6930ffdc87bcc365822b80b90c72d30e955e7870a7a9725e9a946b9e89aec6db9455557eb"
,
"44bf54abcbae297baf3dec4dd998b313eafb01166760f0c3a4b36509b33d3b50239de0a5f2f47c2fc98a98a382dcd95a2c5bf1f4910467418a3c2595b853338e"
,
}
privKeys
=
make
([]
crypto
.
PrivKey
,
len
(
testPrivateKeys
))
testCfg
=
types
.
NewChain33Config
(
types
.
GetDefaultCfgstring
())
)
func
init
()
{
log
.
SetLogLevel
(
"error"
)
Init
(
vty
.
VoteX
,
testCfg
,
nil
)
for
i
,
priv
:=
range
testPrivateKeys
{
privKeys
[
i
],
_
=
decodePrivKey
(
priv
)
}
}
type
testExecMock
struct
{
dbDir
string
localDB
dbm
.
KVDB
stateDB
dbm
.
DB
exec
*
vote
policy
wcom
.
WalletBizPolicy
cfg
*
types
.
Chain33Config
q
queue
.
Queue
qapi
client
.
QueueProtocolAPI
execType
types
.
ExecutorType
}
type
testcase
struct
{
payload
types
.
Message
expectExecErr
error
expectCheckErr
error
expectExecLocalErr
error
expectExecDelErr
error
priv
crypto
.
PrivKey
execType
int
index
int
}
// InitEnv init env
func
(
mock
*
testExecMock
)
InitEnv
()
{
mock
.
cfg
=
testCfg
util
.
ResetDatadir
(
mock
.
cfg
.
GetModuleConfig
(),
"$TEMP/"
)
mock
.
q
=
queue
.
New
(
"channel"
)
mock
.
q
.
SetConfig
(
mock
.
cfg
)
mock
.
qapi
,
_
=
client
.
New
(
mock
.
q
.
Client
(),
nil
)
mock
.
initExec
()
}
func
(
mock
*
testExecMock
)
FreeEnv
()
{
util
.
CloseTestDB
(
mock
.
dbDir
,
mock
.
stateDB
)
}
func
(
mock
*
testExecMock
)
initExec
()
{
mock
.
dbDir
,
mock
.
stateDB
,
mock
.
localDB
=
util
.
CreateTestDB
()
exec
:=
newVote
()
exec
.
SetAPI
(
mock
.
qapi
)
exec
.
SetStateDB
(
mock
.
stateDB
)
exec
.
SetLocalDB
(
mock
.
localDB
)
exec
.
SetEnv
(
testHeight
,
testBlockTime
,
1539918074
)
mock
.
exec
=
exec
.
(
*
vote
)
mock
.
execType
=
types
.
LoadExecutorType
(
vty
.
VoteX
)
}
func
decodePrivKey
(
priv
string
)
(
crypto
.
PrivKey
,
error
)
{
c
,
err
:=
crypto
.
New
(
crypto
.
GetName
(
types
.
SECP256K1
))
if
err
!=
nil
{
return
nil
,
err
}
bytes
,
err
:=
common
.
FromHex
(
priv
[
:
])
if
err
!=
nil
{
return
nil
,
err
}
privKey
,
err
:=
c
.
PrivKeyFromBytes
(
bytes
)
if
err
!=
nil
{
return
nil
,
err
}
return
privKey
,
nil
}
func
createTx
(
mock
*
testExecMock
,
payload
types
.
Message
,
privKey
crypto
.
PrivKey
)
(
*
types
.
Transaction
,
error
)
{
action
,
_
:=
getActionName
(
payload
)
tx
,
err
:=
mock
.
execType
.
CreateTransaction
(
action
,
payload
)
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"createTxErr:"
+
err
.
Error
())
}
tx
,
err
=
types
.
FormatTx
(
mock
.
cfg
,
vty
.
VoteX
,
tx
)
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"formatTxErr:"
+
err
.
Error
())
}
tx
.
Sign
(
int32
(
types
.
SECP256K1
),
privKey
)
return
tx
,
nil
}
func
getActionName
(
param
types
.
Message
)
(
string
,
error
)
{
if
_
,
ok
:=
param
.
(
*
vty
.
CreateGroup
);
ok
{
return
vty
.
NameCreateGroupAction
,
nil
}
else
if
_
,
ok
:=
param
.
(
*
vty
.
UpdateGroup
);
ok
{
return
vty
.
NameUpdateGroupAction
,
nil
}
else
if
_
,
ok
:=
param
.
(
*
vty
.
CreateVote
);
ok
{
return
vty
.
NameCreateVoteAction
,
nil
}
else
if
_
,
ok
:=
param
.
(
*
vty
.
CommitVote
);
ok
{
return
vty
.
NameCommitVoteAction
,
nil
}
else
if
_
,
ok
:=
param
.
(
*
vty
.
CloseVote
);
ok
{
return
vty
.
NameCloseVoteAction
,
nil
}
else
if
_
,
ok
:=
param
.
(
*
vty
.
UpdateMember
);
ok
{
return
vty
.
NameUpdateMemberAction
,
nil
}
else
{
return
""
,
types
.
ErrActionNotSupport
}
}
func
TestUtil
(
t
*
testing
.
T
)
{
heightIndex
:=
dapp
.
HeightIndexStr
(
100
,
0
)
require
.
Equal
(
t
,
IDLen
,
len
(
formatGroupID
(
heightIndex
)))
require
.
Equal
(
t
,
IDLen
,
len
(
formatVoteID
(
heightIndex
)))
strs
:=
[]
string
{
"a"
,
"b"
,
"c"
}
require
.
True
(
t
,
checkSliceItemExist
(
"a"
,
strs
))
require
.
False
(
t
,
checkSliceItemExist
(
"d"
,
strs
))
require
.
False
(
t
,
checkSliceItemDuplicate
(
strs
))
strs
=
append
(
strs
,
"c"
)
require
.
True
(
t
,
checkSliceItemDuplicate
(
strs
))
members
:=
make
([]
*
vty
.
GroupMember
,
0
)
for
_
,
addr
:=
range
testAddrs
{
members
=
append
(
members
,
&
vty
.
GroupMember
{
Addr
:
addr
,
})
}
require
.
True
(
t
,
checkMemberExist
(
testAddrs
[
0
],
members
))
require
.
False
(
t
,
checkMemberExist
(
"testaddr"
,
members
))
require
.
Equal
(
t
,
addrLen
,
len
(
testAddrs
[
0
]))
}
func
TestFilterVoteWithStatus
(
t
*
testing
.
T
)
{
currentTime
:=
types
.
Now
()
.
Unix
()
voteList
:=
[]
*
vty
.
VoteInfo
{
{
BeginTimestamp
:
currentTime
+
1
,
},
{
EndTimestamp
:
currentTime
+
1
,
},
{
BeginTimestamp
:
currentTime
,
EndTimestamp
:
currentTime
,
},
{
Status
:
voteStatusClosed
,
},
}
statusList
:=
[]
uint32
{
voteStatusPending
,
voteStatusOngoing
,
voteStatusFinished
,
voteStatusClosed
}
voteList
=
filterVoteWithStatus
(
voteList
,
0
,
currentTime
)
for
i
,
info
:=
range
voteList
{
require
.
Equal
(
t
,
statusList
[
i
],
info
.
Status
)
}
for
_
,
status
:=
range
statusList
{
list
:=
filterVoteWithStatus
(
voteList
,
status
,
currentTime
)
require
.
Equal
(
t
,
1
,
len
(
list
))
require
.
Equal
(
t
,
status
,
list
[
0
]
.
Status
)
}
}
plugin/dapp/vote/proto/vote.proto
View file @
75d588eb
...
@@ -80,6 +80,7 @@ message CommitVote {
...
@@ -80,6 +80,7 @@ message CommitVote {
message
CommitInfo
{
message
CommitInfo
{
string
addr
=
1
;
//提交地址
string
addr
=
1
;
//提交地址
string
txHash
=
2
;
//提交交易哈希
string
txHash
=
2
;
//提交交易哈希
uint32
voteWeight
=
3
;
//投票权重
}
}
message
CloseVote
{
message
CloseVote
{
...
...
plugin/dapp/vote/types/vote.pb.go
View file @
75d588eb
...
@@ -675,6 +675,7 @@ func (m *CommitVote) GetOptionIndex() uint32 {
...
@@ -675,6 +675,7 @@ func (m *CommitVote) GetOptionIndex() uint32 {
type
CommitInfo
struct
{
type
CommitInfo
struct
{
Addr
string
`protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
Addr
string
`protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
TxHash
string
`protobuf:"bytes,2,opt,name=txHash,proto3" json:"txHash,omitempty"`
TxHash
string
`protobuf:"bytes,2,opt,name=txHash,proto3" json:"txHash,omitempty"`
VoteWeight
uint32
`protobuf:"varint,3,opt,name=voteWeight,proto3" json:"voteWeight,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_unrecognized
[]
byte
`json:"-"`
XXX_sizecache
int32
`json:"-"`
XXX_sizecache
int32
`json:"-"`
...
@@ -719,6 +720,13 @@ func (m *CommitInfo) GetTxHash() string {
...
@@ -719,6 +720,13 @@ func (m *CommitInfo) GetTxHash() string {
return
""
return
""
}
}
func
(
m
*
CommitInfo
)
GetVoteWeight
()
uint32
{
if
m
!=
nil
{
return
m
.
VoteWeight
}
return
0
}
type
CloseVote
struct
{
type
CloseVote
struct
{
VoteID
string
`protobuf:"bytes,1,opt,name=voteID,proto3" json:"voteID,omitempty"`
VoteID
string
`protobuf:"bytes,1,opt,name=voteID,proto3" json:"voteID,omitempty"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
XXX_NoUnkeyedLiteral
struct
{}
`json:"-"`
...
@@ -1267,62 +1275,62 @@ func init() {
...
@@ -1267,62 +1275,62 @@ func init() {
}
}
var
fileDescriptor_21d31c94b62a6ac7
=
[]
byte
{
var
fileDescriptor_21d31c94b62a6ac7
=
[]
byte
{
// 9
04
bytes of a gzipped FileDescriptorProto
// 9
12
bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x94
,
0x56
,
0xdd
,
0x
6e
,
0xeb
,
0x4
4
,
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x94
,
0x56
,
0xdd
,
0x
8e
,
0xe3
,
0x3
4
,
0x1
0
,
0x8e
,
0x9d
,
0xd8
,
0x89
,
0xc7
,
0xcd
,
0xa1
,
0x2c
,
0x28
,
0xb2
,
0x8e
,
0x8e
,
0x50
,
0xb4
,
0x20
,
0x1
4
,
0x6e
,
0x92
,
0x26
,
0x6d
,
0x4e
,
0xa6
,
0xcb
,
0x60
,
0x50
,
0x15
,
0xad
,
0x56
,
0xa8
,
0x32
,
0x08
,
0x
54
,
0xc1
,
0x51
,
0x04
,
0x8d
,
0x84
,
0x0a
,
0xe2
,
0x82
,
0x42
,
0x05
,
0x89
,
0x44
,
0x0b
,
0x5a
,
0xa
0
,
0x
8d
,
0x60
,
0x55
,
0xc1
,
0x56
,
0x42
,
0x80
,
0xb8
,
0x60
,
0x61
,
0x05
,
0xad
,
0xc4
,
0x0c
,
0xc8
,
0xc
0
,
0x
5c
,
0x71
,
0xe1
,
0xda
,
0x4b
,
0x6a
,
0x11
,
0xdb
,
0xa9
,
0x77
,
0x13
,
0x35
,
0x8f
,
0xc0
,
0x73
,
0x71
,
0x
c0
,
0x0d
,
0x17
,
0x99
,
0xc4
,
0x74
,
0x22
,
0x9a
,
0xa4
,
0x13
,
0xbb
,
0xd5
,
0xf4
,
0x11
,
0x78
,
0x2e
,
0x
c7
,
0x25
,
0x6f
,
0x81
,
0xc4
,
0x43
,
0xa0
,
0x9d
,
0xf5
,
0xcf
,
0x3a
,
0x3f
,
0x3a
,
0xed
,
0x5d
,
0x66
,
0x
ee
,
0xb8
,
0xe4
,
0x2d
,
0x90
,
0x78
,
0x08
,
0xe4
,
0xe3
,
0xfc
,
0x38
,
0xfd
,
0xd1
,
0xce
,
0xdc
,
0xf5
,
0x
f6
,
0x9b
,
0x9d
,
0xd9
,
0xef
,
0xfb
,
0x76
,
0x63
,
0x80
,
0x4d
,
0x2e
,
0xf9
,
0x64
,
0x55
,
0xe4
,
0x32
,
0x
1c
,
0x7f
,
0xc7
,
0x3e
,
0xfe
,
0xbe
,
0xcf
,
0xa7
,
0x01
,
0xd8
,
0x16
,
0x92
,
0x4f
,
0xd7
,
0x65
,
0x21
,
0x
27
,
0x8e
,
0xdc
,
0xae
,
0xb8
,
0xa0
,
0xff
,
0xd9
,
0x00
,
0xb7
,
0xb9
,
0xe4
,
0x97
,
0x91
,
0x4c
,
0xf2
,
0x
0b
,
0xe2
,
0xca
,
0xdd
,
0x9a
,
0x0b
,
0xfa
,
0x9f
,
0x0d
,
0x70
,
0x5d
,
0x48
,
0xfe
,
0x32
,
0x96
,
0x69
,
0x
8c
,
0xbc
,
0x00
,
0x5b
,
0x6e
,
0x03
,
0x6b
,
0x6c
,
0x9d
,
0x39
,
0xcc
,
0x96
,
0x5b
,
0xf2
,
0x19
,
0xf8
,
0x
91
,
0x93
,
0x27
,
0x60
,
0xcb
,
0x5d
,
0x68
,
0x4d
,
0xac
,
0x0b
,
0x97
,
0xd9
,
0x72
,
0x47
,
0x3e
,
0x81
,
0x
51
,
0xc1
,
0x43
,
0xc9
,
0xbf
,
0x2b
,
0xf2
,
0xf5
,
0x2a
,
0xb0
,
0xc7
,
0xd6
,
0x99
,
0x7f
,
0x4e
,
0x26
,
0x
20
,
0x2e
,
0x79
,
0x24
,
0xf9
,
0xb7
,
0x65
,
0xb1
,
0x59
,
0x87
,
0xf6
,
0xc4
,
0xba
,
0x08
,
0x5e
,
0x90
,
0x
58
,
0x3b
,
0xf9
,
0xa6
,
0x59
,
0x99
,
0x75
,
0x98
,
0x09
,
0x54
,
0x75
,
0xeb
,
0x55
,
0x5c
,
0xd7
,
0x75
,
0x
29
,
0xd6
,
0x4e
,
0xbf
,
0x6e
,
0x57
,
0xe6
,
0x3d
,
0x66
,
0x02
,
0x55
,
0xdd
,
0x66
,
0x9d
,
0x34
,
0x75
,
0x
5b
,
0x75
,
0xbf
,
0x34
,
0x2b
,
0xaa
,
0xce
,
0x00
,
0x92
,
0x29
,
0x80
,
0xde
,
0x46
,
0xcd
,
0x14
,
0xf4
,
0x
4e
,
0xa7
,
0xee
,
0xe7
,
0x76
,
0x45
,
0xd5
,
0x19
,
0x40
,
0x32
,
0x03
,
0xd0
,
0xdb
,
0xa8
,
0x9e
,
0xc2
,
0x
b0
,
0xec
,
0xed
,
0x56
,
0x3b
,
0xb5
,
0x30
,
0xeb
,
0x30
,
0x03
,
0x86
,
0x45
,
0x79
,
0x9a
,
0x26
,
0x12
,
0x
3e
,
0x96
,
0xbd
,
0xd9
,
0x39
,
0x4e
,
0x2d
,
0xcc
,
0x7b
,
0xcc
,
0x80
,
0x61
,
0x51
,
0x91
,
0x65
,
0xa9
,
0x
8b
,
0x9c
,
0x76
,
0x51
,
0xbd
,
0x80
,
0x45
,
0x75
,
0x44
,
0x3e
,
0x01
,
0x2f
,
0x5a
,
0xe6
,
0x42
,
0x37
,
0x
c4
,
0x22
,
0xb7
,
0x5b
,
0xd4
,
0x2c
,
0x60
,
0x51
,
0x13
,
0x91
,
0x8f
,
0xc0
,
0x8f
,
0x57
,
0x85
,
0xd0
,
0x
72
,
0xb1
,
0xe6
,
0xb4
,
0xaa
,
0xa9
,
0xf2
,
0xb3
,
0x0e
,
0x6b
,
0x40
,
0xe4
,
0x73
,
0x38
,
0xd1
,
0xa3
,
0x
07
,
0x79
,
0x58
,
0x73
,
0x5e
,
0xd7
,
0xd4
,
0xf9
,
0x79
,
0x8f
,
0xb5
,
0x20
,
0xf2
,
0x19
,
0x9c
,
0xe9
,
0x5
e
,
0xf3
,
0xf4
,
0x8e
,
0x17
,
0x41
,
0x1f
,
0x8b
,
0xde
,
0x69
,
0x1d
,
0x4a
,
0x2f
,
0xcd
,
0x3a
,
0xac
,
0x5
6
,
0x2f
,
0x79
,
0x76
,
0xc3
,
0xcb
,
0x70
,
0x80
,
0x45
,
0x6f
,
0x75
,
0x2e
,
0xa5
,
0x97
,
0xe6
,
0x3d
,
0x
05
,
0xfd
,
0xba
,
0x0f
,
0xce
,
0x26
,
0x5c
,
0xae
,
0x39
,
0xfd
,
0x0d
,
0x7c
,
0x3c
,
0xa8
,
0xce
,
0x13
,
0x
d6
,
0x81
,
0x7e
,
0x35
,
0x00
,
0x77
,
0x1b
,
0xad
,
0x36
,
0x9c
,
0xfe
,
0x06
,
0x01
,
0x5e
,
0x54
,
0xe7
,
0x0
2
,
0xbd
,
0x30
,
0x8e
,
0x0b
,
0x24
,
0xdc
,
0x63
,
0xf8
,
0x9b
,
0xbc
,
0xa7
,
0x65
,
0xfa
,
0x95
,
0x27
,
0x0
9
,
0x81
,
0x7e
,
0x94
,
0x24
,
0x25
,
0x12
,
0xee
,
0x33
,
0xfc
,
0x4d
,
0xde
,
0xd1
,
0x32
,
0xfd
,
0xc2
,
0x
8b
,
0x7b
,
0x89
,
0x8c
,
0x0f
,
0x99
,
0x91
,
0x21
,
0x2f
,
0x61
,
0x90
,
0x25
,
0xd1
,
0x1f
,
0x37
,
0x61
,
0x
d3
,
0xe5
,
0xad
,
0x44
,
0xc6
,
0x47
,
0xcc
,
0xc8
,
0x90
,
0xa7
,
0x30
,
0xcc
,
0xd3
,
0xf8
,
0x8f
,
0xab
,
0x
ca
,
0x91
,
0x57
,
0x8f
,
0xd5
,
0x31
,
0xfd
,
0xd3
,
0x02
,
0xdf
,
0x50
,
0x45
,
0xed
,
0x9f
,
0x29
,
0x5c
,
0x
28
,
0xe3
,
0xc8
,
0xab
,
0xcf
,
0x9a
,
0x98
,
0xfe
,
0x69
,
0x41
,
0x60
,
0xa8
,
0xa2
,
0xf6
,
0xcf
,
0x15
,
0x
b9
,
0xbf
,
0xfa
,
0x4d
,
0x46
,
0xe0
,
0x86
,
0x71
,
0x9a
,
0x64
,
0x22
,
0xb0
,
0xc7
,
0xdd
,
0x33
,
0x8f
,
0x
ae
,
0xda
,
0x5f
,
0xfd
,
0x26
,
0x63
,
0xf0
,
0xa2
,
0x24
,
0x4b
,
0x73
,
0x11
,
0xda
,
0x13
,
0xe7
,
0xc2
,
0x
95
,
0x11
,
0x79
,
0x0d
,
0xfd
,
0x14
,
0xa7
,
0x12
,
0x41
,
0x77
,
0xdc
,
0x35
,
0xe4
,
0x32
,
0x06
,
0x66
,
0x
67
,
0x55
,
0x44
,
0x9e
,
0xc3
,
0x20
,
0xc3
,
0xae
,
0x44
,
0xe8
,
0x4c
,
0x1c
,
0x43
,
0x2e
,
0xa3
,
0x61
,
0x
15
,
0x84
,
0x8c
,
0xc1
,
0x8f
,
0xb9
,
0x88
,
0x8a
,
0x64
,
0xa5
,
0x7c
,
0x83
,
0x4a
,
0x79
,
0xcc
,
0x4
c
,
0x
56
,
0x43
,
0xc8
,
0x04
,
0x82
,
0x84
,
0x8b
,
0xb8
,
0x4c
,
0xd7
,
0xca
,
0x37
,
0xa8
,
0x94
,
0xcf
,
0xc
c
,
0x
d1
,
0xbf
,
0x2c
,
0xf0
,
0x0d
,
0xa5
,
0x49
,
0x00
,
0xfd
,
0x85
,
0xfa
,
0x31
,
0xbf
,
0x2a
,
0xc7
,
0xa9
,
0x
14
,
0xfd
,
0xcb
,
0x82
,
0xc0
,
0x50
,
0x9a
,
0x84
,
0x30
,
0x58
,
0xaa
,
0x1f
,
0x8b
,
0x57
,
0x55
,
0x3b
,
0x
42
,
0x72
,
0x0e
,
0x10
,
0xc6
,
0xf1
,
0x75
,
0xd9
,
0xdc
,
0x3e
,
0xda
,
0xdc
,
0x40
,
0x91
,
0x0f
,
0x60
,
0x
75
,
0x48
,
0x5e
,
0x00
,
0x44
,
0x49
,
0x72
,
0x59
,
0x1d
,
0x6e
,
0x9f
,
0x3c
,
0xdc
,
0x40
,
0x91
,
0xf7
,
0x
58
,
0xf0
,
0x34
,
0xdf
,
0xf0
,
0x6b
,
0x63
,
0x66
,
0x8f
,
0xb5
,
0x93
,
0xe4
,
0x15
,
0x78
,
0x61
,
0x1c
,
0x
60
,
0x54
,
0xf2
,
0xac
,
0xd8
,
0xf2
,
0x4b
,
0xa3
,
0x67
,
0x9f
,
0x75
,
0x93
,
0xe4
,
0x19
,
0xf8
,
0x51
,
0x
5f
,
0xea
,
0xe3
,
0xf6
,
0x10
,
0xd1
,
0x24
,
0x08
,
0x85
,
0x13
,
0x0d
,
0x2f
,
0x01
,
0x0e
,
0x02
,
0x5a
,
0x
92
,
0xbc
,
0xd4
,
0xd7
,
0xed
,
0x23
,
0xa2
,
0x4d
,
0x10
,
0x0a
,
0x67
,
0x1a
,
0x5e
,
0x01
,
0x5c
,
0x04
,
0x
39
,
0xfa
,
0xaf
,
0x05
,
0x1e
,
0xce
,
0x30
,
0xcf
,
0x7e
,
0xcf
,
0xd5
,
0xf5
,
0xa8
,
0xc7
,
0xb7
,
0xe7
,
0x
74
,
0x72
,
0xf4
,
0x5f
,
0x0b
,
0x7c
,
0xec
,
0x61
,
0x91
,
0xff
,
0x5e
,
0xa8
,
0xe7
,
0xd1
,
0xb4
,
0x6f
,
0x
57
,
0x35
,
0xbf
,
0xb6
,
0xc1
,
0xef
,
0x2b
,
0xf0
,
0x34
,
0x49
,
0x37
,
0xeb
,
0x14
,
0x05
,
0x1a
,
0xb2
,
0x
2f
,
0x5e
,
0x35
,
0xfc
,
0xda
,
0x06
,
0xbf
,
0xcf
,
0xc0
,
0xd7
,
0x24
,
0x5d
,
0x6d
,
0x32
,
0x14
,
0x68
,
0x
26
,
0xa1
,
0x58
,
0x40
,
0xe7
,
0xe6
,
0x45
,
0xc9
,
0x59
,
0x15
,
0x1a
,
0xba
,
0x38
,
0xc7
,
0x74
,
0x71
,
0x
c4
,
0xda
,
0x84
,
0x62
,
0x01
,
0x9d
,
0x5b
,
0x94
,
0x15
,
0x67
,
0x75
,
0x68
,
0xe8
,
0xe2
,
0x9e
,
0xd2
,
0x
9f
,
0xad
,
0x4b
,
0x7f
,
0x4f
,
0x17
,
0x35
,
0x81
,
0x72
,
0x93
,
0x9a
,
0x6e
,
0x80
,
0xd3
,
0x55
,
0x21
,
0x
c5
,
0x7b
,
0xb4
,
0x2e
,
0x83
,
0x03
,
0x5d
,
0x54
,
0x07
,
0xca
,
0x4d
,
0xaa
,
0xbb
,
0x21
,
0x76
,
0x57
,
0x
fd
,
0x12
,
0xa0
,
0x3e
,
0xaa
,
0x20
,
0x13
,
0xf0
,
0x50
,
0xa0
,
0xef
,
0x13
,
0x21
,
0x03
,
0x0b
,
0x3b
,
0x
87
,
0xf4
,
0x0b
,
0x80
,
0xe6
,
0xaa
,
0x82
,
0x4c
,
0xc1
,
0x47
,
0x81
,
0xbe
,
0x4b
,
0x85
,
0x0c
,
0x2d
,
0x
9f
,
0x9a
,
0x9d
,
0x15
,
0x8a
,
0x35
,
0x10
,
0xfa
,
0x85
,
0x7e
,
0x48
,
0x7e
,
0xd0
,
0x5d
,
0x46
,
0xe0
,
0x
3c
,
0xf9
,
0xdc
,
0x3c
,
0x59
,
0xa1
,
0x58
,
0x0b
,
0xa1
,
0x9f
,
0xeb
,
0x41
,
0xf2
,
0xbd
,
0x3e
,
0x65
,
0x
e6
,
0x7a
,
0x04
,
0xcd
,
0x56
,
0x19
,
0x91
,
0x77
,
0xc1
,
0x11
,
0x51
,
0x5e
,
0xf0
,
0xd2
,
0xd8
,
0x3a
,
0x
0c
,
0x5e
,
0xa1
,
0x5b
,
0xd0
,
0x6c
,
0x55
,
0x11
,
0x79
,
0x1b
,
0x5c
,
0x11
,
0x17
,
0x25
,
0xaf
,
0x8c
,
0xa
0
,
0x7f
,
0x5b
,
0x00
,
0xcd
,
0xf5
,
0x3e
,
0x68
,
0x5b
,
0xc3
,
0x3e
,
0x76
,
0xdb
,
0x3e
,
0x63
,
0xf0
,
0xa
d
,
0x03
,
0xfa
,
0xb7
,
0x05
,
0xd0
,
0x3e
,
0xef
,
0xa3
,
0xb6
,
0x35
,
0xec
,
0x63
,
0x77
,
0xed
,
0x33
,
0x
37
,
0x75
,
0xe3
,
0xca
,
0x08
,
0x66
,
0x8a
,
0x7c
,
0x08
,
0x2f
,
0xee
,
0xf8
,
0x22
,
0xc9
,
0x7e
,
0x4e
,
0x
81
,
0x60
,
0xdb
,
0x1c
,
0x5c
,
0x1b
,
0xc1
,
0x4c
,
0x91
,
0xf7
,
0xe1
,
0xc9
,
0x0d
,
0x5f
,
0xa6
,
0xf9
,
0x
52
,
0x2e
,
0x64
,
0x98
,
0xae
,
0x90
,
0xfb
,
0x2e
,
0xdb
,
0xc9
,
0x2a
,
0x43
,
0xf0
,
0x2c
,
0x6e
,
0x50
,
0x
4f
,
0x69
,
0xc6
,
0x85
,
0x8c
,
0xb2
,
0x35
,
0x72
,
0xef
,
0xb0
,
0xbd
,
0xac
,
0x32
,
0x04
,
0xcf
,
0x93
,
0x
0e
,
0xa2
,
0x5a
,
0xb9
,
0x5d
,
0x82
,
0xdd
,
0x7d
,
0xe3
,
0x7f
,
0x0b
,
0xd0
,
0xbc
,
0x3a
,
0x8a
,
0x08
,
0x
16
,
0xe5
,
0x22
,
0xaa
,
0x93
,
0xdb
,
0x27
,
0xd8
,
0x3b
,
0x34
,
0xfe
,
0x37
,
0x00
,
0xed
,
0xd4
,
0x51
,
0x
35
,
0x4a
,
0x6d
,
0x9b
,
0x32
,
0x52
,
0xfb
,
0x68
,
0x4a
,
0xe6
,
0x59
,
0xcc
,
0x1f
,
0x4b
,
0x3a
,
0xcc
,
0x
44
,
0xa8
,
0x56
,
0x1a
,
0xdb
,
0x54
,
0x91
,
0xda
,
0x47
,
0x53
,
0xb2
,
0xc8
,
0x13
,
0x7e
,
0x5f
,
0xd1
,
0x
14
,
0xbd
,
0xa8
,
0xf6
,
0x41
,
0xeb
,
0x1d
,
0x7a
,
0x2a
,
0x46
,
0xe0
,
0xca
,
0xc7
,
0x59
,
0x28
,
0xee
,
0x
61
,
0xa6
,
0xe8
,
0xaf
,
0xf5
,
0x3e
,
0x68
,
0xbd
,
0x63
,
0xa3
,
0x62
,
0x0c
,
0x9e
,
0xbc
,
0x9f
,
0x47
,
0x
4b
,
0x4a
,
0xca
,
0x88
,
0xbe
,
0x0f
,
0x5e
,
0xfd
,
0x86
,
0x1d
,
0x1b
,
0x80
,
0x52
,
0x38
,
0x31
,
0xdf
,
0x
e2
,
0xb6
,
0xa2
,
0xa4
,
0x8a
,
0xf6
,
0x46
,
0x88
,
0xb3
,
0x3f
,
0x42
,
0xe8
,
0xbb
,
0xe0
,
0x37
,
0x33
,
0x
ac
,
0x43
,
0xa4
,
0xd3
,
0x7f
,
0x6c
,
0x18
,
0xa8
,
0x4d
,
0x9e
,
0x6c
,
0x7e
,
0xc3
,
0xde
,
0xdd
,
0xb
6
,
0x
ee
,
0x54
,
0x83
,
0x94
,
0xc2
,
0x99
,
0x39
,
0xd3
,
0x8e
,
0x89
,
0x42
,
0xff
,
0xb1
,
0x61
,
0xa8
,
0x3
6
,
0x
bd
,
0x0d
,
0xfd
,
0x7a
,
0x6d
,
0xfd
,
0xa6
,
0x6d
,
0xfd
,
0x1c
,
0xb4
,
0x5a
,
0xf5
,
0x7e
,
0x37
,
0x96
,
0x
79
,
0xf0
,
0xe3
,
0x30
,
0xec
,
0xef
,
0x74
,
0xed
,
0x6f
,
0xe8
,
0xdb
,
0xef
,
0xea
,
0x3b
,
0xeb
,
0xea
,
0x
7a
,
0x93
,
0xa4
,
0xee
,
0x93
,
0x24
,
0xed
,
0x1f
,
0x90
,
0x74
,
0x0a
,
0x7e
,
0x54
,
0x13
,
0x2d
,
0x82
,
0x
eb
,
0xa2
,
0x15
,
0xeb
,
0xf9
,
0xde
,
0x5a
,
0xee
,
0x75
,
0x92
,
0x7b
,
0x0f
,
0x92
,
0x7c
,
0x70
,
0x44
,
0x
41
,
0x6b
,
0x80
,
0x46
,
0x02
,
0x66
,
0xa2
,
0x76
,
0x7d
,
0xe0
,
0xed
,
0x5f
,
0xb4
,
0x11
,
0xb8
,
0x42
,
0x
f2
,
0x19
,
0x04
,
0x71
,
0x23
,
0x84
,
0x08
,
0x87
,
0x9d
,
0x06
,
0x5a
,
0x89
,
0x98
,
0x89
,
0xda
,
0xf7
,
0x8
6
,
0x72
,
0x2d
,
0x02
,
0x40
,
0x71
,
0xcb
,
0x88
,
0x5e
,
0x80
,
0x57
,
0x71
,
0x2a
,
0xc8
,
0xc7
,
0x30
,
0x8
9
,
0x7f
,
0xf8
,
0x10
,
0xc7
,
0xe0
,
0x09
,
0x19
,
0xc9
,
0x8d
,
0x08
,
0x01
,
0x15
,
0xaa
,
0x22
,
0xfa
,
0x
50
,
0xc7
,
0x32
,
0x2e
,
0xd9
,
0x5b
,
0xc6
,
0xc9
,
0xb1
,
0x6d
,
0x0d
,
0xa0
,
0x3f
,
0x02
,
0x68
,
0xb1
,
0x
29
,
0xf8
,
0x35
,
0xa7
,
0x82
,
0x7c
,
0x08
,
0x43
,
0x75
,
0x2d
,
0xe3
,
0x11
,
0xbe
,
0x61
,
0xdc
,
0x1c
,
0x8
e
,
0x3a
,
0xe2
,
0x90
,
0x26
,
0x2f
,
0x61
,
0x50
,
0x52
,
0x5d
,
0x5d
,
0x8e
,
0x3a
,
0xa6
,
0x5f
,
0x81
,
0x8
f
,
0x6d
,
0x00
,
0xf4
,
0x07
,
0x00
,
0x2d
,
0xd6
,
0x49
,
0xc7
,
0x1c
,
0xd3
,
0xe4
,
0x29
,
0x0c
,
0x2b
,
0x
df
,
0xec
,
0x28
,
0xc8
,
0xa7
,
0x00
,
0xfa
,
0x21
,
0x31
,
0xe6
,
0xa9
,
0x88
,
0x68
,
0x70
,
0xcc
,
0x00
,
0x
aa
,
0xeb
,
0xc7
,
0xd3
,
0xc4
,
0xf4
,
0x4b
,
0x08
,
0xda
,
0x1d
,
0x05
,
0xf9
,
0x18
,
0x40
,
0x0f
,
0x1a
,
0x
51
,
0x0a
,
0xc0
,
0xf8
,
0xc3
,
0x4f
,
0xb2
,
0x48
,
0xb2
,
0x85
,
0x50
,
0xd7
,
0x3b
,
0x91
,
0x3c
,
0x15
,
0x
a3
,
0x9f
,
0x9a
,
0x88
,
0x16
,
0xc7
,
0x0c
,
0x10
,
0xa5
,
0x00
,
0x8c
,
0xdf
,
0xfd
,
0x28
,
0xcb
,
0x34
,
0x5
8
,
0xeb
,
0x31
,
0x1d
,
0xd0
,
0x08
,
0x7c
,
0xc6
,
0x1f
,
0x14
,
0x7c
,
0x2e
,
0x79
,
0xaa
,
0xa8
,
0x13
,
0x5
f
,
0x0a
,
0xf5
,
0xfc
,
0x53
,
0xc9
,
0x33
,
0x81
,
0xb5
,
0x3e
,
0xd3
,
0x01
,
0x8d
,
0x21
,
0x60
,
0xfc
,
0x
32
,
0x2c
,
0x30
,
0xa8
,
0x1d
,
0x65
,
0xa6
,
0xd4
,
0x36
,
0x51
,
0xbe
,
0xce
,
0xf4
,
0xdf
,
0x9f
,
0xc3
,
0x
4e
,
0xc1
,
0x17
,
0x92
,
0x67
,
0x8a
,
0x3a
,
0x21
,
0xa3
,
0x12
,
0x83
,
0xc6
,
0x51
,
0x66
,
0x4a
,
0x6d
,
0x
74
,
0xa0
,
0x5e
,
0xd6
,
0x38
,
0x29
,
0x38
,
0x7e
,
0xa9
,
0xa0
,
0xbd
,
0x1c
,
0xd6
,
0x24
,
0x68
,
0x5a
,
0x
13
,
0x17
,
0x9b
,
0x5c
,
0xff
,
0x3d
,
0xba
,
0x4c
,
0x07
,
0x6a
,
0xf2
,
0x26
,
0x69
,
0xc9
,
0xf1
,
0x4b
,
0x
37
,
0x41
,
0xdb
,
0x1f
,
0xff
,
0xbb
,
0x79
,
0x0d
,
0xfd
,
0x65
,
0x22
,
0x24
,
0xe3
,
0x0f
,
0x3b
,
0xdf
,
0x
06
,
0xed
,
0xe5
,
0xb2
,
0x36
,
0x41
,
0xb3
,
0xe6
,
0x10
,
0xb4
,
0xfd
,
0xe9
,
0xbf
,
0xa3
,
0xe7
,
0x30
,
0x
33
,
0xc6
,
0x8c
,
0xac
,
0x82
,
0x18
,
0x2a
,
0x76
,
0x5b
,
0x2a
,
0xde
,
0xc3
,
0x90
,
0xf1
,
0xd5
,
0x72
,
0x
58
,
0xa5
,
0x42
,
0x32
,
0x7e
,
0xb7
,
0xf7
,
0xbd
,
0x63
,
0xf4
,
0xc8
,
0x6a
,
0x88
,
0xa1
,
0xa2
,
0xd3
,
0x
7b
,
0x5b
,
0x8a
,
0xf3
,
0x2c
,
0x25
,
0xc9
,
0x47
,
0x70
,
0x1a
,
0xad
,
0x8b
,
0x82
,
0x67
,
0xb2
,
0xb1
,
0x
51
,
0xf1
,
0x16
,
0x46
,
0x8c
,
0xaf
,
0x57
,
0xbb
,
0xeb
,
0x4a
,
0x9c
,
0x47
,
0x29
,
0x49
,
0x3e
,
0x80
,
0x
a6
,
0x8d
,
0xd6
,
0xdc
,
0xcb
,
0xdf
,
0xb9
,
0xf8
,
0xc1
,
0x36
,
0xfd
,
0x3f
,
0x00
,
0x00
,
0xff
,
0xf
f
,
0x
f3
,
0x78
,
0x53
,
0x96
,
0x3c
,
0x97
,
0xad
,
0x35
,
0x6d
,
0xb4
,
0xe6
,
0x41
,
0xfe
,
0xc6
,
0xc3
,
0x0
f
,
0x
d4
,
0x6f
,
0xb9
,
0xbc
,
0xb
e
,
0x09
,
0x00
,
0x00
,
0x
ba
,
0xd9
,
0xff
,
0x01
,
0x00
,
0x00
,
0xff
,
0xff
,
0x1d
,
0x74
,
0x0c
,
0x4b
,
0xd
e
,
0x09
,
0x00
,
0x00
,
}
}
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