Merge pull request #208 from orijtech/build_create
modules/coin/rest: implemented doCreateRole
This commit is contained in:
commit
7b3fde4544
1
Makefile
1
Makefile
|
@ -38,6 +38,7 @@ test_cli: tests/cli/shunit2
|
|||
./tests/cli/roles.sh
|
||||
./tests/cli/counter.sh
|
||||
./tests/cli/restart.sh
|
||||
./tests/cli/rest.sh
|
||||
./tests/cli/ibc.sh
|
||||
|
||||
test_tutorial: docs/guide/shunit2
|
||||
|
|
|
@ -24,11 +24,17 @@ Route | Method | Completed | Description
|
|||
/sign|POST|✔️|Sign a transaction
|
||||
/tx|POST|✖️|Post a transaction to the blockchain
|
||||
/seeds/status|GET|✖️|Returns the information on the last seed
|
||||
/build/create_role|POST|✔️|Creates a role. Please note that the role MUST be valid hex for example instead of sending "role", send its hex encoded equivalent "726f6c65"
|
||||
|
||||
## Preamble:
|
||||
In the examples below, we assume that URL is set to `http://localhost:8889`
|
||||
which can be set for example
|
||||
URL=http://localhost:8889
|
||||
|
||||
## Sample usage
|
||||
- Generate a key
|
||||
```shell
|
||||
$ curl -X POST http://localhost8998/keys --data '{"algo": "ed25519", "name": "SampleX", "passphrase": "Say no more"}'
|
||||
$ curl -X POST $URL/keys --data '{"algo": "ed25519", "name": "SampleX", "passphrase": "Say no more"}'
|
||||
```
|
||||
|
||||
```json
|
||||
|
@ -47,7 +53,7 @@ $ curl -X POST http://localhost8998/keys --data '{"algo": "ed25519", "name": "Sa
|
|||
|
||||
- Sign a key
|
||||
```shell
|
||||
$ curl -X POST http://localhost:8998/sign --data '{
|
||||
$ curl -X POST $URL/sign --data '{
|
||||
"name": "matt",
|
||||
"password": "Say no more",
|
||||
"tx": {
|
||||
|
@ -114,3 +120,41 @@ $ curl -X POST http://localhost:8998/sign --data '{
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Create a role
|
||||
```shell
|
||||
$ curl -X POST $URL/build/create_role --data \
|
||||
'{
|
||||
"role": "deadbeef",
|
||||
"signers": [{
|
||||
"addr": "4FF759D47C81754D8F553DCCAC8651D0AF74C7F9",
|
||||
"app": "role"
|
||||
}],
|
||||
"min_sigs": 1,
|
||||
"seq": 1
|
||||
}'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "chain/tx",
|
||||
"data": {
|
||||
"chain_id": "test_chain_id",
|
||||
"expires_at": 0,
|
||||
"tx": {
|
||||
"type": "role/create",
|
||||
"data": {
|
||||
"role": "DEADBEEF",
|
||||
"min_sigs": 1,
|
||||
"signers": [
|
||||
{
|
||||
"chain": "",
|
||||
"app": "role",
|
||||
"addr": "4FF759D47C81754D8F553DCCAC8651D0AF74C7F9"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/tendermint/basecoin/client/commands"
|
||||
rest "github.com/tendermint/basecoin/client/rest"
|
||||
coinrest "github.com/tendermint/basecoin/modules/coin/rest"
|
||||
rolerest "github.com/tendermint/basecoin/modules/roles/rest"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
)
|
||||
|
||||
|
@ -50,6 +51,9 @@ func serve(cmd *cobra.Command, args []string) error {
|
|||
// Coin query account handler
|
||||
coinrest.RegisterQueryAccount,
|
||||
|
||||
// Roles createRole handler
|
||||
rolerest.RegisterCreateRole,
|
||||
|
||||
// Basecoin sign transactions handler
|
||||
rest.RegisterSignTx,
|
||||
// Basecoin post transaction handler
|
||||
|
|
|
@ -152,3 +152,4 @@ func RegisterAll(r *mux.Router) error {
|
|||
}
|
||||
|
||||
// End of mux.Router registrars
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/basecoin/client/commands"
|
||||
"github.com/tendermint/basecoin/errors"
|
||||
"github.com/tendermint/basecoin/modules/base"
|
||||
"github.com/tendermint/basecoin/modules/nonce"
|
||||
"github.com/tendermint/basecoin/modules/roles"
|
||||
"github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
// RoleInput encapsulates the fields needed to create a role
|
||||
type RoleInput struct {
|
||||
// Role is a hex encoded string of the role name
|
||||
// for example, instead of "role" as the name, its
|
||||
// hex encoded version "726f6c65".
|
||||
Role string `json:"role" validate:"required,min=2"`
|
||||
|
||||
MinimumSigners uint32 `json:"min_sigs" validate:"required,min=1"`
|
||||
|
||||
Signers []basecoin.Actor `json:"signers" validate:"required,min=1"`
|
||||
|
||||
// Sequence is the user defined field whose purpose is to
|
||||
// prevent replay attacks when creating a role, since it
|
||||
// ensures that for a successful role creation, the previous
|
||||
// sequence number should have been looked up by the caller.
|
||||
Sequence uint32 `json:"seq" validate:"required,min=1"`
|
||||
}
|
||||
|
||||
func decodeRoleHex(roleInHex string) ([]byte, error) {
|
||||
parsedRole, err := hex.DecodeString(common.StripHex(roleInHex))
|
||||
if err != nil {
|
||||
err = errors.WithMessage("invalid hex", err, abci.CodeType_EncodingError)
|
||||
return nil, err
|
||||
}
|
||||
return parsedRole, nil
|
||||
}
|
||||
|
||||
// mux.Router registrars
|
||||
|
||||
// RegisterCreateRole is a mux.Router handler that exposes POST
|
||||
// method access on route /build/create_role to create a role.
|
||||
func RegisterCreateRole(r *mux.Router) error {
|
||||
r.HandleFunc("/build/create_role", doCreateRole).Methods("POST")
|
||||
return nil
|
||||
}
|
||||
|
||||
func doCreateRole(w http.ResponseWriter, r *http.Request) {
|
||||
ri := new(RoleInput)
|
||||
if err := common.ParseRequestAndValidateJSON(r, ri); err != nil {
|
||||
common.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
parsedRole, err := decodeRoleHex(ri.Role)
|
||||
if err != nil {
|
||||
common.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Note the ordering of Tx wrapping matters:
|
||||
// 1. NonceTx
|
||||
tx := (nonce.Tx{}).Wrap()
|
||||
tx = nonce.NewTx(ri.Sequence, ri.Signers, tx)
|
||||
|
||||
// 2. CreateRoleTx
|
||||
tx = roles.NewCreateRoleTx(parsedRole, ri.MinimumSigners, ri.Signers)
|
||||
|
||||
// 3. ChainTx
|
||||
tx = base.NewChainTx(commands.GetChainID(), 0, tx)
|
||||
|
||||
common.WriteSuccess(w, tx)
|
||||
}
|
||||
|
||||
// End of mux.Router registrars
|
|
@ -39,14 +39,13 @@ restAccount() {
|
|||
assertNotNull "line=${LINENO}, address required" "$1"
|
||||
ACCT=$(curl ${URL}/query/account/sigs:$1 2>/dev/null)
|
||||
if [ -n "$DEBUG" ]; then echo $ACCT; echo; fi
|
||||
assertEquals "line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .coins[0].amount)
|
||||
# assertEquals "line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .data.coins[0].amount)
|
||||
assertEquals "line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .data.coins[0].amount)
|
||||
return $?
|
||||
}
|
||||
|
||||
restNoAccount() {
|
||||
ERROR=$(curl ${URL}/query/account/sigs:$1 2>/dev/null)
|
||||
assertEquals "line=${LINENO}, should error" 406 $(echo $ERROR | jq .code)
|
||||
assertEquals "line=${LINENO}, should error" 400 $(echo $ERROR | jq .code)
|
||||
}
|
||||
|
||||
test00GetAccount() {
|
||||
|
@ -57,6 +56,36 @@ test00GetAccount() {
|
|||
restNoAccount $RECV
|
||||
}
|
||||
|
||||
# XXX Ex Usage: restCreateRole $PAYLOAD $EXPECTED
|
||||
# Desc: Tests that the first returned signer.addr matches the expected
|
||||
restCreateRole() {
|
||||
assertNotNull "line=${LINENO}, data required" "$1"
|
||||
ROLE=$(curl ${URL}/build/create_role --data "$1" 2>/dev/null)
|
||||
if [ -n "$DEBUG" ]; then echo -e "$ROLE\n"; fi
|
||||
assertEquals "line=${LINENO}, role required" "$2" $(echo $ROLE | jq .data.tx.data.signers[0].addr)
|
||||
return $?
|
||||
}
|
||||
|
||||
test03CreateRole() {
|
||||
DATA="{\"role\": \"726f6c65\", \"seq\": 1, \"min_sigs\": 1, \"signers\": [{\"addr\": \"4FF759D47C81754D8F553DCCAC8651D0AF74C7F9\", \"app\": \"role\"}]}"
|
||||
restCreateRole "$DATA" \""4FF759D47C81754D8F553DCCAC8651D0AF74C7F9"\"
|
||||
}
|
||||
|
||||
test04CreateRoleInvalid() {
|
||||
ERROR=$(curl ${URL}/build/create_role --data '{}' 2>/dev/null)
|
||||
assertEquals "line=${LINENO}, should report validation failed" 0 $(echo $ERROR | grep "failed" > /dev/null && echo 0 || echo 1)
|
||||
|
||||
ERROR=$(curl ${URL}/build/create_role --data '{"role": "foo"}' 2>/dev/null)
|
||||
assertEquals "line=${LINENO}, should report validation failed" 0 $(echo $ERROR | grep "failed" > /dev/null && echo 0 || echo 1)
|
||||
|
||||
ERROR=$(curl ${URL}/build/create_role --data '{"min_sigs": 2, "role": "abcdef"}' 2>/dev/null)
|
||||
assertEquals "line=${LINENO}, should report validation failed" 0 $(echo $ERROR | grep "failed" > /dev/null && echo 0 || echo 1)
|
||||
|
||||
## Non-hex roles should be rejected
|
||||
ERROR=$(curl ${URL}/build/create_role --data "{\"role\": \"foobar\", \"seq\": 2, \"signers\": [{\"addr\": \"4FF759D47C81754D8F553DCCAC8651D0AF74C7F9\", \"app\": \"role\"}], \"min_sigs\": 1}" 2>/dev/null)
|
||||
assertEquals "line=${LINENO}, should report validation failed" 0 $(echo $ERROR | grep "invalid hex" > /dev/null && echo 0 || echo 1)
|
||||
}
|
||||
|
||||
test01SendTx() {
|
||||
SENDER=$(restAddr $RICH)
|
||||
RECV=$(restAddr $POOR)
|
||||
|
|
Loading…
Reference in New Issue