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
6e108ab9
Commit
6e108ab9
authored
Jul 17, 2019
by
liuyuhang
Committed by
33cn
Aug 14, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add rule project rpc and cmd
parent
72e879e6
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
812 additions
and
5 deletions
+812
-5
proposal_board.go
plugin/dapp/autonomy/commands/proposal_board.go
+22
-3
proposal_project.go
plugin/dapp/autonomy/commands/proposal_project.go
+253
-0
proposal_rule.go
plugin/dapp/autonomy/commands/proposal_rule.go
+208
-0
board.go
plugin/dapp/autonomy/executor/board.go
+0
-1
exec.go
plugin/dapp/autonomy/executor/exec.go
+26
-0
exec_del_local.go
plugin/dapp/autonomy/executor/exec_del_local.go
+22
-0
exec_local.go
plugin/dapp/autonomy/executor/exec_local.go
+27
-0
project.go
plugin/dapp/autonomy/executor/project.go
+0
-1
query.go
plugin/dapp/autonomy/executor/query.go
+6
-0
rule.go
plugin/dapp/autonomy/executor/rule.go
+131
-0
jrpc.go
plugin/dapp/autonomy/rpc/jrpc.go
+55
-0
rpc.go
plugin/dapp/autonomy/rpc/rpc.go
+62
-0
No files found.
plugin/dapp/autonomy/commands/proposal_board.go
View file @
6e108ab9
...
...
@@ -32,6 +32,25 @@ func AutonomyCmd() *cobra.Command {
ShowProposalBoardCmd
(),
)
// project
cmd
.
AddCommand
(
ProposalProjectCmd
(),
RevokeProposalProjectCmd
(),
VoteProposalProjectCmd
(),
PubVoteProposalProjectCmd
(),
TerminateProposalProjectCmd
(),
ShowProposalProjectCmd
(),
)
// rule
cmd
.
AddCommand
(
ProposalRuleCmd
(),
RevokeProposalRuleCmd
(),
VoteProposalRuleCmd
(),
TerminateProposalRuleCmd
(),
ShowProposalRuleCmd
(),
)
return
cmd
}
...
...
@@ -67,7 +86,7 @@ func proposalBoard(cmd *cobra.Command, args []string) {
startBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"startBlock"
)
endBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"endBlock"
)
boardstr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"
gameName
"
)
boardstr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"
boards
"
)
boards
:=
strings
.
Split
(
boardstr
,
"-"
)
...
...
@@ -113,7 +132,7 @@ func revokeProposalBoard(cmd *cobra.Command, args []string) {
ctx
.
RunWithoutMarshal
()
}
//
RevokeProposalBoardCmd 撤销
提案
//
VoteProposalBoardCmd 投票
提案
func
VoteProposalBoardCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"voteBoard"
,
...
...
@@ -144,7 +163,7 @@ func voteProposalBoard(cmd *cobra.Command, args []string) {
ctx
.
RunWithoutMarshal
()
}
// TerminateProposalBoard
撤销
提案
// TerminateProposalBoard
终止
提案
func
TerminateProposalBoardCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"terminateBoard"
,
...
...
plugin/dapp/autonomy/commands/proposal_project.go
View file @
6e108ab9
...
...
@@ -4,4 +4,256 @@
package
commands
import
(
"github.com/spf13/cobra"
"github.com/33cn/chain33/types"
jsonrpc
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes
"github.com/33cn/chain33/rpc/types"
auty
"github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
// ProposalProjectCmd 创建提案命令
func
ProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"proposalProject"
,
Short
:
"create proposal Project"
,
Run
:
proposalProject
,
}
addProposalProjectFlags
(
cmd
)
return
cmd
}
func
addProposalProjectFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
Int32P
(
"year"
,
"y"
,
0
,
"year"
)
cmd
.
Flags
()
.
Int32P
(
"month"
,
"m"
,
0
,
"month"
)
cmd
.
Flags
()
.
Int32P
(
"day"
,
"d"
,
0
,
"day"
)
cmd
.
Flags
()
.
StringP
(
"firstStage"
,
"firstStage"
,
""
,
"first stage proposal ID"
)
cmd
.
Flags
()
.
StringP
(
"lastStage"
,
"lastStage"
,
""
,
"last stage proposal ID"
)
cmd
.
Flags
()
.
StringP
(
"production"
,
"production"
,
""
,
"production address"
)
cmd
.
Flags
()
.
StringP
(
"description"
,
"description"
,
""
,
"description project"
)
cmd
.
Flags
()
.
StringP
(
"contractor"
,
"contractor"
,
""
,
"contractor introduce"
)
cmd
.
Flags
()
.
Int64P
(
"amount"
,
"a"
,
0
,
"project cost amount"
)
cmd
.
MarkFlagRequired
(
"amount"
)
cmd
.
Flags
()
.
StringP
(
"amountDetail"
,
"detail"
,
""
,
"project cost amount detail"
)
cmd
.
Flags
()
.
StringP
(
"toAddr"
,
"to"
,
""
,
"project contractor account address"
)
cmd
.
MarkFlagRequired
(
"toAddr"
)
cmd
.
Flags
()
.
Int64P
(
"startBlock"
,
"s"
,
0
,
"start block height"
)
cmd
.
MarkFlagRequired
(
"startBlock"
)
cmd
.
Flags
()
.
Int64P
(
"endBlock"
,
"e"
,
0
,
"end block height"
)
cmd
.
MarkFlagRequired
(
"endBlock"
)
cmd
.
Flags
()
.
Int32P
(
"projectNeedBlockNum"
,
"n"
,
0
,
"project complete need time(unit is block number)"
)
cmd
.
MarkFlagRequired
(
"projectNeedBlockNum"
)
}
func
proposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
year
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"year"
)
month
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"month"
)
day
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"day"
)
firstStage
,
_
:=
cmd
.
Flags
()
.
GetString
(
"firstStage"
)
lastStage
,
_
:=
cmd
.
Flags
()
.
GetString
(
"lastStage"
)
production
,
_
:=
cmd
.
Flags
()
.
GetString
(
"production"
)
description
,
_
:=
cmd
.
Flags
()
.
GetString
(
"description"
)
contractor
,
_
:=
cmd
.
Flags
()
.
GetString
(
"contractor"
)
amount
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"amount"
)
amountDetail
,
_
:=
cmd
.
Flags
()
.
GetString
(
"amountDetail"
)
toAddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"toAddr"
)
startBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"startBlock"
)
endBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"endBlock"
)
projectNeedBlockNum
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"projectNeedBlockNum"
)
params
:=
&
auty
.
ProposalProject
{
Year
:
year
,
Month
:
month
,
Day
:
day
,
FirstStage
:
firstStage
,
LastStage
:
lastStage
,
Production
:
production
,
Description
:
description
,
Contractor
:
contractor
,
Amount
:
amount
*
types
.
Coin
,
AmountDetail
:
amountDetail
,
ToAddr
:
toAddr
,
StartBlockHeight
:
startBlock
,
EndBlockHeight
:
endBlock
,
ProjectNeedBlockNum
:
projectNeedBlockNum
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.PropProjectTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// RevokeProposalProjectCmd 撤销提案
func
RevokeProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"revokeProject"
,
Short
:
"revoke proposal Project"
,
Run
:
revokeProposalProject
,
}
addRevokeProposalProjectFlags
(
cmd
)
return
cmd
}
func
addRevokeProposalProjectFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
}
func
revokeProposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
params
:=
&
auty
.
RevokeProposalProject
{
ProposalID
:
ID
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.RevokeProposalProjectTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// VoteProposalProjectCmd 投票提案
func
VoteProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"voteProject"
,
Short
:
"vote proposal Project"
,
Run
:
voteProposalProject
,
}
addVoteProposalProjectFlags
(
cmd
)
return
cmd
}
func
addVoteProposalProjectFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
cmd
.
Flags
()
.
BoolP
(
"approve"
,
"ap"
,
true
,
"is approve, default true"
)
}
func
voteProposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
approve
,
_
:=
cmd
.
Flags
()
.
GetBool
(
"approve"
)
params
:=
&
auty
.
VoteProposalProject
{
ProposalID
:
ID
,
Approve
:
approve
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.VoteProposalProjectTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// PubVoteProposalProjectCmd 全员投票提案
func
PubVoteProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"pubvoteProject"
,
Short
:
"pub vote proposal Project"
,
Run
:
pubVoteProposalProject
,
}
addPubVoteProposalProjectFlags
(
cmd
)
return
cmd
}
func
addPubVoteProposalProjectFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
cmd
.
Flags
()
.
BoolP
(
"oppose"
,
"op"
,
true
,
"is oppose, default true"
)
}
func
pubVoteProposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
oppose
,
_
:=
cmd
.
Flags
()
.
GetBool
(
"oppose"
)
params
:=
&
auty
.
PubVoteProposalProject
{
ProposalID
:
ID
,
Oppose
:
oppose
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.PubVoteProposalProjectTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// TerminateProposalProject 终止提案
func
TerminateProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"terminateProject"
,
Short
:
"terminate proposal Project"
,
Run
:
terminateProposalProject
,
}
addTerminateProposalProjectFlags
(
cmd
)
return
cmd
}
func
addTerminateProposalProjectFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
}
func
terminateProposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
params
:=
&
auty
.
RevokeProposalProject
{
ProposalID
:
ID
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.TerminateProposalProjectTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// ShowProposalProjectCmd 显示提案查询信息
func
ShowProposalProjectCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"showInfo"
,
Short
:
"show proposal Project info"
,
Run
:
showProposalProject
,
}
addShowProposalProjectflags
(
cmd
)
return
cmd
}
func
addShowProposalProjectflags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
Uint32P
(
"type"
,
"t"
,
0
,
"type"
)
cmd
.
MarkFlagRequired
(
"type"
)
cmd
.
Flags
()
.
Uint32P
(
"status"
,
"s"
,
0
,
"status"
)
cmd
.
Flags
()
.
Int32P
(
"count"
,
"c"
,
0
,
"count"
)
cmd
.
Flags
()
.
Int32P
(
"direction"
,
"d"
,
0
,
"direction"
)
cmd
.
Flags
()
.
Int64P
(
"index"
,
"i"
,
0
,
"index"
)
}
func
showProposalProject
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
typ
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"type"
)
status
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"status"
)
count
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"count"
)
direction
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"direction"
)
index
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"index"
)
var
params
rpctypes
.
Query4Jrpc
var
rep
interface
{}
params
.
Execer
=
auty
.
AutonomyX
if
0
==
typ
{
req
:=
auty
.
ReqQueryProposalProject
{
Status
:
int32
(
status
),
Count
:
count
,
Direction
:
direction
,
Index
:
index
,
}
params
.
FuncName
=
auty
.
GetProposalProject
params
.
Payload
=
types
.
MustPBToJSON
(
&
req
)
rep
=
&
auty
.
ReplyQueryProposalProject
{}
}
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"Chain33.Query"
,
params
,
rep
)
ctx
.
Run
()
}
\ No newline at end of file
plugin/dapp/autonomy/commands/proposal_rule.go
View file @
6e108ab9
...
...
@@ -3,3 +3,210 @@
// license that can be found in the LICENSE file.
package
commands
import
(
jsonrpc
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes
"github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/spf13/cobra"
auty
"github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
// ProposalRuleCmd 创建提案命令
func
ProposalRuleCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"proposalRule"
,
Short
:
"create proposal Rule"
,
Run
:
proposalRule
,
}
addProposalRuleFlags
(
cmd
)
return
cmd
}
func
addProposalRuleFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
Int32P
(
"year"
,
"y"
,
0
,
"year"
)
cmd
.
Flags
()
.
Int32P
(
"month"
,
"m"
,
0
,
"month"
)
cmd
.
Flags
()
.
Int32P
(
"day"
,
"d"
,
0
,
"day"
)
cmd
.
Flags
()
.
Int64P
(
"startBlock"
,
"s"
,
0
,
"start block height"
)
cmd
.
MarkFlagRequired
(
"startBlock"
)
cmd
.
Flags
()
.
Int64P
(
"endBlock"
,
"e"
,
0
,
"end block height"
)
cmd
.
MarkFlagRequired
(
"endBlock"
)
// 可修改规则
cmd
.
Flags
()
.
Int32P
(
"boardAttendRatio"
,
"attend"
,
0
,
"board attend ratio(unit is %)"
)
cmd
.
Flags
()
.
Int32P
(
"boardApproveRatio"
,
"approve"
,
0
,
"board approve ratio(unit is %)"
)
cmd
.
Flags
()
.
Int32P
(
"pubOpposeRatio"
,
"oppose"
,
0
,
"public oppose ratio(unit is %)"
)
cmd
.
Flags
()
.
Int64P
(
"proposalAmount"
,
"pa"
,
0
,
"proposal cost amount"
)
cmd
.
Flags
()
.
Int64P
(
"largeProjectAmount"
,
"la"
,
0
,
"large project amount threshold"
)
}
func
proposalRule
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
year
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"year"
)
month
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"month"
)
day
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"day"
)
startBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"startBlock"
)
endBlock
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"endBlock"
)
boardAttendRatio
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"boardAttendRatio"
)
boardApproveRatio
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"boardApproveRatio"
)
pubOpposeRatio
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"pubOpposeRatio"
)
proposalAmount
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"proposalAmount"
)
largeProjectAmount
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"largeProjectAmount"
)
params
:=
&
auty
.
ProposalRule
{
Year
:
year
,
Month
:
month
,
Day
:
day
,
RuleCfg
:
&
auty
.
RuleConfig
{
BoardAttendRatio
:
boardAttendRatio
,
BoardApproveRatio
:
boardApproveRatio
,
PubOpposeRatio
:
pubOpposeRatio
,
ProposalAmount
:
proposalAmount
*
types
.
Coin
,
LargeProjectAmount
:
largeProjectAmount
*
types
.
Coin
,
},
StartBlockHeight
:
startBlock
,
EndBlockHeight
:
endBlock
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.PropRuleTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// RevokeProposalRuleCmd 撤销提案
func
RevokeProposalRuleCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"revokeRule"
,
Short
:
"revoke proposal Rule"
,
Run
:
revokeProposalRule
,
}
addRevokeProposalRuleFlags
(
cmd
)
return
cmd
}
func
addRevokeProposalRuleFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
}
func
revokeProposalRule
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
params
:=
&
auty
.
RevokeProposalRule
{
ProposalID
:
ID
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.RevokeProposalRuleTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// VoteProposalRuleCmd 投票提案
func
VoteProposalRuleCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"voteRule"
,
Short
:
"vote proposal Rule"
,
Run
:
voteProposalRule
,
}
addVoteProposalRuleFlags
(
cmd
)
return
cmd
}
func
addVoteProposalRuleFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
cmd
.
Flags
()
.
BoolP
(
"approve"
,
"ap"
,
true
,
"is approve, default true"
)
}
func
voteProposalRule
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
approve
,
_
:=
cmd
.
Flags
()
.
GetBool
(
"approve"
)
params
:=
&
auty
.
VoteProposalRule
{
ProposalID
:
ID
,
Approve
:
approve
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.VoteProposalRuleTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// TerminateProposalRule 终止提案
func
TerminateProposalRuleCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"terminateRule"
,
Short
:
"terminate proposal Rule"
,
Run
:
terminateProposalRule
,
}
addTerminateProposalRuleFlags
(
cmd
)
return
cmd
}
func
addTerminateProposalRuleFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"proposalID"
,
"p"
,
""
,
"proposal ID"
)
cmd
.
MarkFlagRequired
(
"proposalID"
)
}
func
terminateProposalRule
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
ID
,
_
:=
cmd
.
Flags
()
.
GetString
(
"proposalID"
)
params
:=
&
auty
.
RevokeProposalRule
{
ProposalID
:
ID
,
}
var
res
string
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"autonomy.TerminateProposalRuleTx"
,
params
,
&
res
)
ctx
.
RunWithoutMarshal
()
}
// ShowProposalRuleCmd 显示提案查询信息
func
ShowProposalRuleCmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"showInfo"
,
Short
:
"show proposal Rule info"
,
Run
:
showProposalRule
,
}
addShowProposalRuleflags
(
cmd
)
return
cmd
}
func
addShowProposalRuleflags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
Uint32P
(
"type"
,
"t"
,
0
,
"type"
)
cmd
.
MarkFlagRequired
(
"type"
)
cmd
.
Flags
()
.
Uint32P
(
"status"
,
"s"
,
0
,
"status"
)
cmd
.
Flags
()
.
Int32P
(
"count"
,
"c"
,
0
,
"count"
)
cmd
.
Flags
()
.
Int32P
(
"direction"
,
"d"
,
0
,
"direction"
)
cmd
.
Flags
()
.
Int64P
(
"index"
,
"i"
,
0
,
"index"
)
}
func
showProposalRule
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
typ
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"type"
)
status
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"status"
)
count
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"count"
)
direction
,
_
:=
cmd
.
Flags
()
.
GetInt32
(
"direction"
)
index
,
_
:=
cmd
.
Flags
()
.
GetInt64
(
"index"
)
var
params
rpctypes
.
Query4Jrpc
var
rep
interface
{}
params
.
Execer
=
auty
.
AutonomyX
if
0
==
typ
{
req
:=
auty
.
ReqQueryProposalRule
{
Status
:
int32
(
status
),
Count
:
count
,
Direction
:
direction
,
Index
:
index
,
}
params
.
FuncName
=
auty
.
GetProposalRule
params
.
Payload
=
types
.
MustPBToJSON
(
&
req
)
rep
=
&
auty
.
ReplyQueryProposalRule
{}
}
ctx
:=
jsonrpc
.
NewRPCCtx
(
rpcLaddr
,
"Chain33.Query"
,
params
,
rep
)
ctx
.
Run
()
}
\ No newline at end of file
plugin/dapp/autonomy/executor/board.go
View file @
6e108ab9
...
...
@@ -94,7 +94,6 @@ func delBoardHeightIndex(res *auty.ReceiptProposalBoard) (kvs []*types.KeyValue)
return
kvs
}
// getProposalBoard
func
(
a
*
Autonomy
)
getProposalBoard
(
req
*
auty
.
ReqQueryProposalBoard
)
(
types
.
Message
,
error
)
{
if
req
==
nil
{
return
nil
,
types
.
ErrInvalidParam
...
...
plugin/dapp/autonomy/executor/exec.go
View file @
6e108ab9
...
...
@@ -63,4 +63,29 @@ func (a *Autonomy) Exec_PubVotePropProject(payload *auty.PubVoteProposalProject,
func
(
a
*
Autonomy
)
Exec_TmintPropProject
(
payload
*
auty
.
TerminateProposalProject
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newAction
(
a
,
tx
,
int32
(
index
))
return
action
.
tmintPropProject
(
payload
)
}
// 提案规则相关
// Exec_PropRule 创建提案规则
func
(
a
*
Autonomy
)
Exec_PropRule
(
payload
*
auty
.
ProposalRule
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newAction
(
a
,
tx
,
int32
(
index
))
return
action
.
propRule
(
payload
)
}
// Exec_RvkPropRule 撤销提案规则
func
(
a
*
Autonomy
)
Exec_RvkPropRule
(
payload
*
auty
.
RevokeProposalRule
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newAction
(
a
,
tx
,
int32
(
index
))
return
action
.
rvkPropRule
(
payload
)
}
// Exec_VotePropRule 投票提案规则
func
(
a
*
Autonomy
)
Exec_VotePropRule
(
payload
*
auty
.
VoteProposalRule
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newAction
(
a
,
tx
,
int32
(
index
))
return
action
.
votePropRule
(
payload
)
}
// Exec_TmintPropRule 终止提案规则
func
(
a
*
Autonomy
)
Exec_TmintPropRule
(
payload
*
auty
.
TerminateProposalRule
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
action
:=
newAction
(
a
,
tx
,
int32
(
index
))
return
action
.
tmintPropRule
(
payload
)
}
\ No newline at end of file
plugin/dapp/autonomy/executor/exec_del_local.go
View file @
6e108ab9
...
...
@@ -54,4 +54,25 @@ func (a *Autonomy) ExecDelLocal_PubVotePropProject(payload *auty.PubVoteProposal
// ExecDelLocal_TmintPropProject 终止提案
func
(
a
*
Autonomy
)
ExecDelLocal_TmintPropProject
(
payload
*
auty
.
TerminateProposalProject
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execDelLocalProject
(
receiptData
)
}
// 提案规则相关
// ExecDelLocal_PropRule 创建提案规则
func
(
a
*
Autonomy
)
ExecDelLocal_PropRule
(
payload
*
auty
.
ProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execDelLocalRule
(
receiptData
)
}
// ExecDelLocal_RvkPropRule 撤销提案规则
func
(
a
*
Autonomy
)
ExecDelLocal_RvkPropRule
(
payload
*
auty
.
RevokeProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
){
return
a
.
execDelLocalRule
(
receiptData
)
}
// ExecDelLocal_VotePropRule 投票提案规则
func
(
a
*
Autonomy
)
ExecDelLocal_VotePropRule
(
payload
*
auty
.
VoteProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execDelLocalRule
(
receiptData
)
}
// ExecDelLocal_TmintPropRule 终止提案规则
func
(
a
*
Autonomy
)
ExecDelLocal_TmintPropRule
(
payload
*
auty
.
TerminateProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execDelLocalRule
(
receiptData
)
}
\ No newline at end of file
plugin/dapp/autonomy/executor/exec_local.go
View file @
6e108ab9
...
...
@@ -46,7 +46,33 @@ func (a *Autonomy) ExecLocal_VotePropProject(payload *auty.VoteProposalProject,
return
a
.
execLocalProject
(
receiptData
)
}
// ExecLocal_PubVotePropProject 全体投票提案项目
func
(
a
*
Autonomy
)
ExecLocal_PubVotePropProject
(
payload
*
auty
.
PubVoteProposalProject
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execLocalProject
(
receiptData
)
}
// ExecLocal_TmintPropProject 终止提案项目
func
(
a
*
Autonomy
)
ExecLocal_TmintPropProject
(
payload
*
auty
.
TerminateProposalProject
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execLocalProject
(
receiptData
)
}
// 提案规则相关
// ExecLocal_PropRule 创建提案规则
func
(
a
*
Autonomy
)
ExecLocal_PropRule
(
payload
*
auty
.
ProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execLocalRule
(
receiptData
)
}
// ExecLocal_RvkPropRule 撤销提案规则
func
(
a
*
Autonomy
)
ExecLocal_RvkPropRule
(
payload
*
auty
.
RevokeProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
){
return
a
.
execLocalRule
(
receiptData
)
}
// ExecLocal_VotePropRule 投票提案规则
func
(
a
*
Autonomy
)
ExecLocal_VotePropRule
(
payload
*
auty
.
VoteProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execLocalRule
(
receiptData
)
}
// ExecLocal_TmintPropRule 终止提案规则
func
(
a
*
Autonomy
)
ExecLocal_TmintPropRule
(
payload
*
auty
.
TerminateProposalRule
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
return
a
.
execLocalRule
(
receiptData
)
}
\ No newline at end of file
plugin/dapp/autonomy/executor/project.go
View file @
6e108ab9
...
...
@@ -95,7 +95,6 @@ func delProjectHeightIndex(res *auty.ReceiptProposalProject) (kvs []*types.KeyVa
return
kvs
}
// getProposalBoard
func
(
a
*
Autonomy
)
getProposalProject
(
req
*
auty
.
ReqQueryProposalProject
)
(
types
.
Message
,
error
)
{
if
req
==
nil
{
return
nil
,
types
.
ErrInvalidParam
...
...
plugin/dapp/autonomy/executor/query.go
View file @
6e108ab9
...
...
@@ -17,4 +17,9 @@ func (a *Autonomy) Query_GetProposalBoard(in *auty.ReqQueryProposalBoard) (types
// Query_GetProposalProject 查询提案项目
func
(
a
*
Autonomy
)
Query_GetProposalProject
(
in
*
auty
.
ReqQueryProposalProject
)
(
types
.
Message
,
error
)
{
return
a
.
getProposalProject
(
in
)
}
// Query_GetProposalRule 查询提案规则
func
(
a
*
Autonomy
)
Query_GetProposalRule
(
in
*
auty
.
ReqQueryProposalRule
)
(
types
.
Message
,
error
)
{
return
a
.
getProposalRule
(
in
)
}
\ No newline at end of file
plugin/dapp/autonomy/executor/rule.go
0 → 100644
View file @
6e108ab9
// 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
executor
import
(
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
auty
"github.com/33cn/plugin/plugin/dapp/autonomy/types"
)
func
(
a
*
Autonomy
)
execLocalRule
(
receiptData
*
types
.
ReceiptData
)
(
*
types
.
LocalDBSet
,
error
)
{
dbSet
:=
&
types
.
LocalDBSet
{}
var
set
[]
*
types
.
KeyValue
for
_
,
log
:=
range
receiptData
.
Logs
{
switch
log
.
Ty
{
case
auty
.
TyLogPropRule
,
auty
.
TyLogRvkPropRule
,
auty
.
TyLogVotePropRule
,
auty
.
TyLogTmintPropRule
:
{
var
receipt
auty
.
ReceiptProposalRule
err
:=
types
.
Decode
(
log
.
Log
,
&
receipt
)
if
err
!=
nil
{
return
nil
,
err
}
kv
:=
saveRuleHeightIndex
(
&
receipt
)
set
=
append
(
set
,
kv
...
)
}
default
:
break
}
}
dbSet
.
KV
=
append
(
dbSet
.
KV
,
set
...
)
return
dbSet
,
nil
}
func
saveRuleHeightIndex
(
res
*
auty
.
ReceiptProposalRule
)
(
kvs
[]
*
types
.
KeyValue
)
{
// 先将之前的状态删除掉,再做更新
if
res
.
Current
.
Status
>
1
{
kv
:=
&
types
.
KeyValue
{}
kv
.
Key
=
calcRuleKey4StatusHeight
(
res
.
Prev
.
Status
,
dapp
.
HeightIndexStr
(
res
.
Prev
.
Height
,
int64
(
res
.
Prev
.
Index
)))
kv
.
Value
=
nil
kvs
=
append
(
kvs
,
kv
)
}
kv
:=
&
types
.
KeyValue
{}
kv
.
Key
=
calcRuleKey4StatusHeight
(
res
.
Current
.
Status
,
dapp
.
HeightIndexStr
(
res
.
Current
.
Height
,
int64
(
res
.
Current
.
Index
)))
kv
.
Value
=
types
.
Encode
(
res
.
Current
)
kvs
=
append
(
kvs
,
kv
)
return
kvs
}
func
(
a
*
Autonomy
)
execDelLocalRule
(
receiptData
*
types
.
ReceiptData
)
(
*
types
.
LocalDBSet
,
error
)
{
dbSet
:=
&
types
.
LocalDBSet
{}
var
set
[]
*
types
.
KeyValue
for
_
,
log
:=
range
receiptData
.
Logs
{
switch
log
.
Ty
{
case
auty
.
TyLogPropRule
,
auty
.
TyLogRvkPropRule
,
auty
.
TyLogVotePropRule
,
auty
.
TyLogTmintPropRule
:
{
var
receipt
auty
.
ReceiptProposalRule
err
:=
types
.
Decode
(
log
.
Log
,
&
receipt
)
if
err
!=
nil
{
return
nil
,
err
}
kv
:=
delRuleHeightIndex
(
&
receipt
)
set
=
append
(
set
,
kv
...
)
}
default
:
break
}
}
dbSet
.
KV
=
append
(
dbSet
.
KV
,
set
...
)
return
dbSet
,
nil
}
func
delRuleHeightIndex
(
res
*
auty
.
ReceiptProposalRule
)
(
kvs
[]
*
types
.
KeyValue
)
{
kv
:=
&
types
.
KeyValue
{}
kv
.
Key
=
calcRuleKey4StatusHeight
(
res
.
Current
.
Status
,
dapp
.
HeightIndexStr
(
res
.
Current
.
Height
,
int64
(
res
.
Current
.
Index
)))
kv
.
Value
=
nil
kvs
=
append
(
kvs
,
kv
)
if
res
.
Current
.
Status
>
1
{
kv
:=
&
types
.
KeyValue
{}
kv
.
Key
=
calcRuleKey4StatusHeight
(
res
.
Prev
.
Status
,
dapp
.
HeightIndexStr
(
res
.
Prev
.
Height
,
int64
(
res
.
Prev
.
Index
)))
kv
.
Value
=
types
.
Encode
(
res
.
Prev
)
kvs
=
append
(
kvs
,
kv
)
}
return
kvs
}
func
(
a
*
Autonomy
)
getProposalRule
(
req
*
auty
.
ReqQueryProposalRule
)
(
types
.
Message
,
error
)
{
if
req
==
nil
{
return
nil
,
types
.
ErrInvalidParam
}
var
key
[]
byte
var
values
[][]
byte
var
err
error
localDb
:=
a
.
GetLocalDB
()
if
req
.
GetIndex
()
==
-
1
{
key
=
nil
}
else
{
//翻页查找指定的txhash列表
heightstr
:=
genHeightIndexStr
(
req
.
GetIndex
())
key
=
calcRuleKey4StatusHeight
(
req
.
Status
,
heightstr
)
}
prefix
:=
calcRuleKey4StatusHeight
(
req
.
Status
,
""
)
values
,
err
=
localDb
.
List
(
prefix
,
key
,
req
.
Count
,
req
.
GetDirection
())
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
values
)
==
0
{
return
nil
,
types
.
ErrNotFound
}
var
rep
auty
.
ReplyQueryProposalRule
for
_
,
value
:=
range
values
{
prop
:=
&
auty
.
AutonomyProposalRule
{}
err
=
types
.
Decode
(
value
,
prop
)
if
err
!=
nil
{
return
nil
,
err
}
rep
.
PropRules
=
append
(
rep
.
PropRules
,
prop
)
}
return
&
rep
,
nil
}
\ No newline at end of file
plugin/dapp/autonomy/rpc/jrpc.go
View file @
6e108ab9
...
...
@@ -131,4 +131,58 @@ func (c *Jrpc) TerminateProposalProjectTx(parm *auty.TerminateProposalProject, r
*
result
=
hex
.
EncodeToString
(
reply
.
Data
)
return
nil
}
// 提案规则相关
// PropRuleTx 提案规则RPC接口
func
(
c
*
Jrpc
)
PropRuleTx
(
parm
*
auty
.
ProposalRule
,
result
*
interface
{})
error
{
if
parm
==
nil
{
return
types
.
ErrInvalidParam
}
reply
,
err
:=
c
.
cli
.
propRule
(
context
.
Background
(),
parm
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
reply
.
Data
)
return
nil
}
// RevokeProposalRuleTx 撤销提案规则RPC接口
func
(
c
*
Jrpc
)
RevokeProposalRuleTx
(
parm
*
auty
.
RevokeProposalRule
,
result
*
interface
{})
error
{
if
parm
==
nil
{
return
types
.
ErrInvalidParam
}
reply
,
err
:=
c
.
cli
.
revokeProposalRule
(
context
.
Background
(),
parm
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
reply
.
Data
)
return
nil
}
// VoteProposalRuleTx 投票提案规则RPC接口
func
(
c
*
Jrpc
)
VoteProposalRuleTx
(
parm
*
auty
.
VoteProposalRule
,
result
*
interface
{})
error
{
if
parm
==
nil
{
return
types
.
ErrInvalidParam
}
reply
,
err
:=
c
.
cli
.
voteProposalRule
(
context
.
Background
(),
parm
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
reply
.
Data
)
return
nil
}
// TerminateProposalRuleTx 终止提案规则RPC接口
func
(
c
*
Jrpc
)
TerminateProposalRuleTx
(
parm
*
auty
.
TerminateProposalRule
,
result
*
interface
{})
error
{
if
parm
==
nil
{
return
types
.
ErrInvalidParam
}
reply
,
err
:=
c
.
cli
.
terminateProposalRule
(
context
.
Background
(),
parm
)
if
err
!=
nil
{
return
err
}
*
result
=
hex
.
EncodeToString
(
reply
.
Data
)
return
nil
}
\ No newline at end of file
plugin/dapp/autonomy/rpc/rpc.go
View file @
6e108ab9
...
...
@@ -146,4 +146,65 @@ func (c *channelClient) terminateProposalProject(ctx context.Context, head *auty
return
nil
,
err
}
return
&
types
.
UnsignTx
{
Data
:
data
},
nil
}
// Proposal Rule 相关的接口
func
(
c
*
channelClient
)
propRule
(
ctx
context
.
Context
,
head
*
auty
.
ProposalRule
)
(
*
types
.
UnsignTx
,
error
)
{
val
:=
&
auty
.
AutonomyAction
{
Ty
:
auty
.
AutonomyActionPropRule
,
Value
:
&
auty
.
AutonomyAction_PropRule
{
PropRule
:
head
},
}
tx
:=
&
types
.
Transaction
{
Payload
:
types
.
Encode
(
val
),
}
data
,
err
:=
types
.
FormatTxEncode
(
types
.
ExecName
(
auty
.
AutonomyX
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
types
.
UnsignTx
{
Data
:
data
},
nil
}
func
(
c
*
channelClient
)
revokeProposalRule
(
ctx
context
.
Context
,
head
*
auty
.
RevokeProposalRule
)
(
*
types
.
UnsignTx
,
error
)
{
val
:=
&
auty
.
AutonomyAction
{
Ty
:
auty
.
AutonomyActionRvkPropRule
,
Value
:
&
auty
.
AutonomyAction_RvkPropRule
{
RvkPropRule
:
head
},
}
tx
:=
&
types
.
Transaction
{
Payload
:
types
.
Encode
(
val
),
}
data
,
err
:=
types
.
FormatTxEncode
(
types
.
ExecName
(
auty
.
AutonomyX
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
types
.
UnsignTx
{
Data
:
data
},
nil
}
func
(
c
*
channelClient
)
voteProposalRule
(
ctx
context
.
Context
,
head
*
auty
.
VoteProposalRule
)
(
*
types
.
UnsignTx
,
error
)
{
val
:=
&
auty
.
AutonomyAction
{
Ty
:
auty
.
AutonomyActionVotePropRule
,
Value
:
&
auty
.
AutonomyAction_VotePropRule
{
VotePropRule
:
head
},
}
tx
:=
&
types
.
Transaction
{
Payload
:
types
.
Encode
(
val
),
}
data
,
err
:=
types
.
FormatTxEncode
(
types
.
ExecName
(
auty
.
AutonomyX
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
types
.
UnsignTx
{
Data
:
data
},
nil
}
func
(
c
*
channelClient
)
terminateProposalRule
(
ctx
context
.
Context
,
head
*
auty
.
TerminateProposalRule
)
(
*
types
.
UnsignTx
,
error
)
{
val
:=
&
auty
.
AutonomyAction
{
Ty
:
auty
.
AutonomyActionTmintPropRule
,
Value
:
&
auty
.
AutonomyAction_TmintPropRule
{
TmintPropRule
:
head
},
}
tx
:=
&
types
.
Transaction
{
Payload
:
types
.
Encode
(
val
),
}
data
,
err
:=
types
.
FormatTxEncode
(
types
.
ExecName
(
auty
.
AutonomyX
),
tx
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
types
.
UnsignTx
{
Data
:
data
},
nil
}
\ No newline at end of file
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