mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 06:15:33 +00:00
abci-cli: Add process_proposal command to abci-cli (#8901)
* Add `process_proposal` command to abci-cli * Added process proposal to the 'tutorial' examples * Added entry in CHANGELOG_PENDING.md * Allow empty blocks in PrepareProposal, ProcessProposal, and FinalizeBlock * Fix minimum arguments * Add tests for empty block * Updated abci-cli doc Co-authored-by: Sergio Mena <sergio@informal.systems> Co-authored-by: Jasmina Malicevic <jasmina.dustinac@gmail.com>
This commit is contained in:
@@ -33,6 +33,7 @@ Special thanks to external contributors on this release:
|
||||
- [abci] \#8664 Move `app_hash` parameter from `Commit` to `FinalizeBlock`. (@sergio-mena)
|
||||
- [abci] \#8656 Added cli command for `PrepareProposal`. (@jmalicevic)
|
||||
- [sink/psql] \#8637 tx_results emitted from psql sink are now json encoded, previously they were protobuf encoded
|
||||
- [abci] \#8901 Added cli command for `ProcessProposal`. (@hvanz)
|
||||
|
||||
- P2P Protocol
|
||||
|
||||
|
||||
@@ -79,10 +79,11 @@ func RootCmmand(logger log.Logger) *cobra.Command {
|
||||
// Structure for data passed to print response.
|
||||
type response struct {
|
||||
// generic abci response
|
||||
Data []byte
|
||||
Code uint32
|
||||
Info string
|
||||
Log string
|
||||
Data []byte
|
||||
Code uint32
|
||||
Info string
|
||||
Log string
|
||||
Status int32
|
||||
|
||||
Query *queryResponse
|
||||
}
|
||||
@@ -132,6 +133,7 @@ func addCommands(cmd *cobra.Command, logger log.Logger) {
|
||||
cmd.AddCommand(versionCmd)
|
||||
cmd.AddCommand(testCmd)
|
||||
cmd.AddCommand(prepareProposalCmd)
|
||||
cmd.AddCommand(processProposalCmd)
|
||||
cmd.AddCommand(getQueryCmd())
|
||||
|
||||
// examples
|
||||
@@ -172,7 +174,7 @@ This command opens an interactive console for running any of the other commands
|
||||
without opening a new connection each time
|
||||
`,
|
||||
Args: cobra.ExactArgs(0),
|
||||
ValidArgs: []string{"echo", "info", "query", "check_tx", "prepare_proposal", "finalize_block", "commit"},
|
||||
ValidArgs: []string{"echo", "info", "query", "check_tx", "prepare_proposal", "process_proposal", "finalize_block", "commit"},
|
||||
RunE: cmdConsole,
|
||||
}
|
||||
|
||||
@@ -195,7 +197,7 @@ var finalizeBlockCmd = &cobra.Command{
|
||||
Use: "finalize_block",
|
||||
Short: "deliver a block of transactions to the application",
|
||||
Long: "deliver a block of transactions to the application",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Args: cobra.MinimumNArgs(0),
|
||||
RunE: cmdFinalizeBlock,
|
||||
}
|
||||
|
||||
@@ -230,10 +232,18 @@ var prepareProposalCmd = &cobra.Command{
|
||||
Use: "prepare_proposal",
|
||||
Short: "prepare proposal",
|
||||
Long: "prepare proposal",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Args: cobra.MinimumNArgs(0),
|
||||
RunE: cmdPrepareProposal,
|
||||
}
|
||||
|
||||
var processProposalCmd = &cobra.Command{
|
||||
Use: "process_proposal",
|
||||
Short: "process proposal",
|
||||
Long: "process proposal",
|
||||
Args: cobra.MinimumNArgs(0),
|
||||
RunE: cmdProcessProposal,
|
||||
}
|
||||
|
||||
func getQueryCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "query",
|
||||
@@ -352,6 +362,11 @@ func cmdTest(cmd *cobra.Command, args []string) error {
|
||||
types.TxRecord_UNMODIFIED,
|
||||
}, nil)
|
||||
},
|
||||
func() error {
|
||||
return servertest.ProcessProposal(ctx, client, [][]byte{
|
||||
{0x01},
|
||||
}, types.ResponseProcessProposal_ACCEPT)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -454,6 +469,8 @@ func muxOnCommands(cmd *cobra.Command, pArgs []string) error {
|
||||
return cmdQuery(cmd, actualArgs)
|
||||
case "prepare_proposal":
|
||||
return cmdPrepareProposal(cmd, actualArgs)
|
||||
case "process_proposal":
|
||||
return cmdProcessProposal(cmd, actualArgs)
|
||||
default:
|
||||
return cmdUnimplemented(cmd, pArgs)
|
||||
}
|
||||
@@ -517,13 +534,6 @@ const codeBad uint32 = 10
|
||||
|
||||
// Append new txs to application
|
||||
func cmdFinalizeBlock(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
printResponse(cmd, args, response{
|
||||
Code: codeBad,
|
||||
Log: "Must provide at least one transaction",
|
||||
})
|
||||
return nil
|
||||
}
|
||||
txs := make([][]byte, len(args))
|
||||
for i, arg := range args {
|
||||
txBytes, err := stringOrHexToBytes(arg)
|
||||
@@ -633,15 +643,8 @@ func inTxArray(txByteArray [][]byte, tx []byte) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func cmdPrepareProposal(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
printResponse(cmd, args, response{
|
||||
Code: codeBad,
|
||||
Info: "Must provide at least one transaction",
|
||||
Log: "Must provide at least one transaction",
|
||||
})
|
||||
return nil
|
||||
}
|
||||
txsBytesArray := make([][]byte, len(args))
|
||||
|
||||
for i, arg := range args {
|
||||
@@ -682,6 +685,30 @@ func cmdPrepareProposal(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdProcessProposal(cmd *cobra.Command, args []string) error {
|
||||
txsBytesArray := make([][]byte, len(args))
|
||||
|
||||
for i, arg := range args {
|
||||
txBytes, err := stringOrHexToBytes(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
txsBytesArray[i] = txBytes
|
||||
}
|
||||
|
||||
res, err := client.ProcessProposal(cmd.Context(), &types.RequestProcessProposal{
|
||||
Txs: txsBytesArray,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printResponse(cmd, args, response{
|
||||
Status: int32(res.Status),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeKVStoreCmd(logger log.Logger) func(*cobra.Command, []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
// Create the application - in memory or persisted to disk
|
||||
@@ -739,6 +766,9 @@ func printResponse(cmd *cobra.Command, args []string, rsps ...response) {
|
||||
if rsp.Log != "" {
|
||||
fmt.Printf("-> log: %s\n", rsp.Log)
|
||||
}
|
||||
if cmd.Use == "process_proposal" {
|
||||
fmt.Printf("-> status: %s\n", types.ResponseProcessProposal_ProposalStatus_name[rsp.Status])
|
||||
}
|
||||
|
||||
if rsp.Query != nil {
|
||||
fmt.Printf("-> height: %d\n", rsp.Query.Height)
|
||||
|
||||
@@ -293,7 +293,7 @@ func (app *Application) PrepareProposal(_ context.Context, req *types.RequestPre
|
||||
|
||||
func (*Application) ProcessProposal(_ context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
|
||||
for _, tx := range req.Txs {
|
||||
if len(tx) == 0 {
|
||||
if len(tx) == 0 || isPrepareTx(tx) {
|
||||
return &types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,19 @@ func PrepareProposal(ctx context.Context, client abciclient.Client, txBytes [][]
|
||||
fmt.Println("Passed test: PrepareProposal")
|
||||
return nil
|
||||
}
|
||||
|
||||
func ProcessProposal(ctx context.Context, client abciclient.Client, txBytes [][]byte, statusExp types.ResponseProcessProposal_ProposalStatus) error {
|
||||
res, _ := client.ProcessProposal(ctx, &types.RequestProcessProposal{Txs: txBytes})
|
||||
if res.Status != statusExp {
|
||||
fmt.Println("Failed test: ProcessProposal")
|
||||
fmt.Printf("ProcessProposal response status was unexpected. Got %v expected %v.",
|
||||
res.Status, statusExp)
|
||||
return errors.New("ProcessProposal error")
|
||||
}
|
||||
fmt.Println("Passed test: ProcessProposal")
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckTx(ctx context.Context, client abciclient.Client, txBytes []byte, codeExp uint32, dataExp []byte) error {
|
||||
res, _ := client.CheckTx(ctx, &types.RequestCheckTx{Tx: txBytes})
|
||||
code, data := res.Code, res.Data
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
echo hello
|
||||
info
|
||||
prepare_proposal "abc"
|
||||
process_proposal "abc"
|
||||
finalize_block "abc"
|
||||
commit
|
||||
info
|
||||
@@ -8,4 +9,10 @@ query "abc"
|
||||
finalize_block "def=xyz" "ghi=123"
|
||||
commit
|
||||
query "def"
|
||||
prepare_proposal "preparedef"
|
||||
prepare_proposal "preparedef"
|
||||
process_proposal "def"
|
||||
process_proposal "preparedef"
|
||||
prepare_proposal
|
||||
process_proposal
|
||||
finalize_block
|
||||
commit
|
||||
@@ -12,6 +12,10 @@
|
||||
-> code: OK
|
||||
-> log: Succeeded. Tx: abc action: UNMODIFIED
|
||||
|
||||
> process_proposal "abc"
|
||||
-> code: OK
|
||||
-> status: ACCEPT
|
||||
|
||||
> finalize_block "abc"
|
||||
-> code: OK
|
||||
-> code: OK
|
||||
@@ -58,3 +62,24 @@
|
||||
-> code: OK
|
||||
-> log: Succeeded. Tx: preparedef action: REMOVED
|
||||
|
||||
> process_proposal "def"
|
||||
-> code: OK
|
||||
-> status: ACCEPT
|
||||
|
||||
> process_proposal "preparedef"
|
||||
-> code: OK
|
||||
-> status: REJECT
|
||||
|
||||
> prepare_proposal
|
||||
|
||||
> process_proposal
|
||||
-> code: OK
|
||||
-> status: ACCEPT
|
||||
|
||||
> finalize_block
|
||||
-> code: OK
|
||||
-> data.hex: 0x0600000000000000
|
||||
|
||||
> commit
|
||||
-> code: OK
|
||||
|
||||
|
||||
@@ -208,6 +208,33 @@ Try running these commands:
|
||||
-> key.hex: 646566
|
||||
-> value: xyz
|
||||
-> value.hex: 78797A
|
||||
|
||||
> prepare_proposal "preparedef"
|
||||
-> code: OK
|
||||
-> log: Succeeded. Tx: def action: ADDED
|
||||
-> code: OK
|
||||
-> log: Succeeded. Tx: preparedef action: REMOVED
|
||||
|
||||
> process_proposal "def"
|
||||
-> code: OK
|
||||
-> status: ACCEPT
|
||||
|
||||
> process_proposal "preparedef"
|
||||
-> code: OK
|
||||
-> status: REJECT
|
||||
|
||||
> prepare_proposal
|
||||
|
||||
> process_proposal
|
||||
-> code: OK
|
||||
-> status: ACCEPT
|
||||
|
||||
> finalize_block
|
||||
-> code: OK
|
||||
-> data.hex: 0x0600000000000000
|
||||
|
||||
> commit
|
||||
-> code: OK
|
||||
```
|
||||
|
||||
Note that if we do `finalize_block "abc" ...` it will store `(abc, abc)`, but if
|
||||
|
||||
Reference in New Issue
Block a user