move things to _attic
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`"
|
||||
|
||||
install:
|
||||
@go install -ldflags $(LINKER_FLAGS) ./cmd/...
|
||||
|
||||
test: test_unit test_cli
|
||||
|
||||
test_unit:
|
||||
@go test `glide novendor`
|
||||
|
||||
test_cli:
|
||||
./tests/cli/keys.sh
|
||||
./tests/cli/rpc.sh
|
||||
./tests/cli/init.sh
|
||||
./tests/cli/init-server.sh
|
||||
./tests/cli/basictx.sh
|
||||
./tests/cli/roles.sh
|
||||
./tests/cli/restart.sh
|
||||
./tests/cli/rest.sh
|
||||
./tests/cli/ibc.sh
|
||||
|
||||
.PHONY: install test test_unit test_cli
|
||||
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// AppAccount - coin account structure
|
||||
type AppAccount struct {
|
||||
Address_ types.Address `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
PubKey_ crypto.PubKey `json:"public_key"` // can't conflict with PubKey()
|
||||
Sequence int64 `json:"sequence"`
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Get(key interface{}) (value interface{}, err error) {
|
||||
switch key.(type) {
|
||||
case string:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Set(key interface{}, value interface{}) error {
|
||||
switch key.(type) {
|
||||
case string:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Address() types.Address {
|
||||
return a.PubKey_.Address()
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) PubKey() crypto.PubKey {
|
||||
return a.PubKey_
|
||||
}
|
||||
|
||||
func (a *AppAccount) SetPubKey(pubKey crypto.PubKey) error {
|
||||
a.PubKey_ = pubKey
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (a *AppAccount) GetCoins() types.Coins {
|
||||
return a.Coins
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (a *AppAccount) SetCoins(coins types.Coins) error {
|
||||
a.Coins = coins
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AppAccount) GetSequence() int64 {
|
||||
return a.Sequence
|
||||
}
|
||||
|
||||
func (a *AppAccount) SetSequence(seq int64) error {
|
||||
a.Sequence = seq
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type AppAccountStore struct {
|
||||
kvStore types.KVStore
|
||||
}
|
||||
|
||||
func newAccountStore(kvStore types.KVStore) types.AccountStore {
|
||||
return AppAccountStore{kvStore}
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) NewAccountWithAddress(addr types.Address) types.Account {
|
||||
return &AppAccount{
|
||||
Address_: addr,
|
||||
}
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) GetAccount(addr types.Address) types.Account {
|
||||
v := accStore.kvStore.Get(keyAccount(addr))
|
||||
|
||||
if len(v) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
acc := new(AppAccount)
|
||||
if err := json.Unmarshal(v, acc); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return acc
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) SetAccount(acc types.Account) {
|
||||
b, err := json.Marshal(acc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
appAcc, ok := acc.(*AppAccount)
|
||||
if !ok {
|
||||
panic("acc is not *AppAccount") // XXX
|
||||
}
|
||||
|
||||
accStore.kvStore.Set(keyAccount(appAcc.Address_), b)
|
||||
}
|
||||
|
||||
func keyAccount(addr types.Address) []byte {
|
||||
return []byte(path.Join("account", string(addr)))
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// XXX Rename AppHandler to DefaultAppHandler.
|
||||
// XXX Register with a sdk.BaseApp instance to create Basecoin.
|
||||
// XXX Create TxParser in anotehr file.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
)
|
||||
|
||||
// AppHandler has no state for now, a more complex app could store state here
|
||||
type AppHandler struct{}
|
||||
|
||||
func NewAppHandler() sdk.Handler {
|
||||
return AppHandler{}
|
||||
}
|
||||
|
||||
// DeliverTx applies the tx
|
||||
func (h Handler) DeliverTx(ctx sdk.Context, store store.MultiStore,
|
||||
msg interface{}) (res sdk.DeliverResult, err error) {
|
||||
|
||||
db := store.Get("main").(sdk.KVStore)
|
||||
|
||||
// Here we switch on which implementation of tx we use,
|
||||
// and then take the appropriate action.
|
||||
switch tx := tx.(type) {
|
||||
case SendTx:
|
||||
err = tx.ValidateBasic()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
db.Set(tx.Key, tx.Value)
|
||||
res.Data = tx.Key
|
||||
case RemoveTx:
|
||||
err = tx.ValidateBasic()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
db.Remove(tx.Key)
|
||||
res.Data = tx.Key
|
||||
default:
|
||||
err = errors.ErrInvalidFormat(TxWrapper{}, msg)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CheckTx verifies if it is legit and returns info on how
|
||||
// to prioritize it in the mempool
|
||||
func (h Handler) CheckTx(ctx sdk.Context, store store.MultiStore,
|
||||
msg interface{}) (res sdk.CheckResult, err error) {
|
||||
|
||||
// If we wanted to use the store,
|
||||
// it would look the same (as DeliverTx)
|
||||
// db := store.Get("main").(sdk.KVStore)
|
||||
|
||||
// Make sure it is something valid
|
||||
tx, ok := msg.(Tx)
|
||||
if !ok {
|
||||
return res, errors.ErrInvalidFormat(TxWrapper{}, msg)
|
||||
}
|
||||
err = tx.ValidateBasic()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Now return the costs (these should have meaning in your app)
|
||||
return sdk.CheckResult{
|
||||
GasAllocated: 50,
|
||||
GasPayment: 10,
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
# Run your own (super) lightweight node
|
||||
|
||||
In addition to providing command-line tooling that goes cryptographic verification
|
||||
on all the data your receive from the node, we have implemented a proxy mode, that
|
||||
allows you to run a super lightweight node. It does not follow the chain on
|
||||
every block or even every header, but only as needed. But still providing the
|
||||
same security as running a full non-validator node on your local machine.
|
||||
|
||||
Basically, it runs as a proxy that exposes the same rpc interface as the full node
|
||||
and connects to a (potentially untrusted) full node. Every response is cryptographically
|
||||
verified before being passed through, returning an error if it doesn't match.
|
||||
|
||||
You can expect 2 rpc calls for every query plus <= 1 query for each validator set
|
||||
change. Going offline for a while allows you to verify multiple validator set changes
|
||||
with one call. Cuz at 1 block/sec and 1000 tx/block, it just doesn't make sense
|
||||
to run a full node just to get security
|
||||
|
||||
## Setup
|
||||
|
||||
Just initialize your client with the proper validator set as in the [README](README.md)
|
||||
|
||||
```
|
||||
$ export BCHOME=~/.lightnode
|
||||
$ basecli init --node tcp://<host>:<port> --chain-id <chain>
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```
|
||||
$ basecli proxy --serve tcp://localhost:7890
|
||||
...
|
||||
curl localhost:7890/status
|
||||
curl localhost:7890/block\?height=20
|
||||
```
|
||||
|
||||
You can even subscribe to events over websockets and they are all verified
|
||||
before passing them though. Though if you want every block, you might as
|
||||
well run a full (nonvalidating) node.
|
||||
|
||||
## Seeds
|
||||
|
||||
Every time the validator set changes, the light node verifies if it is legal,
|
||||
and then creates a seed at that point. These "seeds" are verified checkpoints
|
||||
that we can trace any proof back to, starting with one on `init`.
|
||||
|
||||
To make sure you are based on the most recent header, you can run:
|
||||
|
||||
```
|
||||
basecli seeds update
|
||||
basecli seeds show
|
||||
```
|
||||
|
||||
## Feedback
|
||||
|
||||
This is the first release of basecli and the light-weight proxy. It is secure, but
|
||||
may not be useful for your workflow. Please try it out and open github issues
|
||||
for any enhancements or bugs you find. I am aiming to make this a very useful
|
||||
tool by tendermint 0.11, for which I need community feedback.
|
||||
@@ -1,53 +0,0 @@
|
||||
# Basic run through of using basecli....
|
||||
|
||||
To keep things clear, let's have two shells...
|
||||
|
||||
`$` is for basecoin (server), `%` is for basecli (client)
|
||||
|
||||
## Set up your basecli with a new key
|
||||
|
||||
```
|
||||
% export BCHOME=~/.democli
|
||||
% basecli keys new demo
|
||||
% basecli keys get demo -o json
|
||||
```
|
||||
|
||||
And set up a few more keys for fun...
|
||||
|
||||
```
|
||||
% basecli keys new buddy
|
||||
% basecli keys list
|
||||
% ME=$(basecli keys get demo | awk '{print $2}')
|
||||
% YOU=$(basecli keys get buddy | awk '{print $2}')
|
||||
```
|
||||
|
||||
## Set up a clean basecoin, initialized with your account
|
||||
|
||||
```
|
||||
$ export BCHOME=~/.demoserve
|
||||
$ basecoin init $ME
|
||||
$ basecoin start
|
||||
```
|
||||
|
||||
## Connect your basecli the first time
|
||||
|
||||
```
|
||||
% basecli init --chain-id test_chain_id --node tcp://localhost:46657
|
||||
```
|
||||
|
||||
## Check your balances...
|
||||
|
||||
```
|
||||
% basecli query account $ME
|
||||
% basecli query account $YOU
|
||||
```
|
||||
|
||||
## Send the money
|
||||
|
||||
```
|
||||
% basecli tx send --name demo --amount 1000mycoin --sequence 1 --to $YOU
|
||||
-> copy hash to HASH
|
||||
% basecli query tx $HASH
|
||||
% basecli query account $YOU
|
||||
```
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/auto"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/proxy"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc"
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands"
|
||||
basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands"
|
||||
coincmd "github.com/cosmos/cosmos-sdk/modules/coin/commands"
|
||||
feecmd "github.com/cosmos/cosmos-sdk/modules/fee/commands"
|
||||
ibccmd "github.com/cosmos/cosmos-sdk/modules/ibc/commands"
|
||||
noncecmd "github.com/cosmos/cosmos-sdk/modules/nonce/commands"
|
||||
rolecmd "github.com/cosmos/cosmos-sdk/modules/roles/commands"
|
||||
)
|
||||
|
||||
// BaseCli - main basecoin client command
|
||||
var BaseCli = &cobra.Command{
|
||||
Use: "basecli",
|
||||
Short: "Light client for Tendermint",
|
||||
Long: `Basecli is a certifying light client for the basecoin abci app.
|
||||
|
||||
It leverages the power of the tendermint consensus algorithm get full
|
||||
cryptographic proof of all queries while only syncing a fraction of the
|
||||
block headers.`,
|
||||
}
|
||||
|
||||
func main() {
|
||||
commands.AddBasicFlags(BaseCli)
|
||||
|
||||
// Prepare queries
|
||||
query.RootCmd.AddCommand(
|
||||
// These are default parsers, but optional in your app (you can remove key)
|
||||
query.TxQueryCmd,
|
||||
query.KeyQueryCmd,
|
||||
coincmd.AccountQueryCmd,
|
||||
noncecmd.NonceQueryCmd,
|
||||
rolecmd.RoleQueryCmd,
|
||||
ibccmd.IBCQueryCmd,
|
||||
)
|
||||
|
||||
// set up the middleware
|
||||
txcmd.Middleware = txcmd.Wrappers{
|
||||
feecmd.FeeWrapper{},
|
||||
rolecmd.RoleWrapper{},
|
||||
noncecmd.NonceWrapper{},
|
||||
basecmd.ChainWrapper{},
|
||||
authcmd.SigWrapper{},
|
||||
}
|
||||
txcmd.Middleware.Register(txcmd.RootCmd.PersistentFlags())
|
||||
|
||||
// you will always want this for the base send command
|
||||
txcmd.RootCmd.AddCommand(
|
||||
// This is the default transaction, optional in your app
|
||||
coincmd.SendTxCmd,
|
||||
coincmd.CreditTxCmd,
|
||||
// this enables creating roles
|
||||
rolecmd.CreateRoleTxCmd,
|
||||
// these are for handling ibc
|
||||
ibccmd.RegisterChainTxCmd,
|
||||
ibccmd.UpdateChainTxCmd,
|
||||
ibccmd.PostPacketTxCmd,
|
||||
)
|
||||
|
||||
// Set up the various commands to use
|
||||
BaseCli.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.ResetCmd,
|
||||
keys.RootCmd,
|
||||
commits.RootCmd,
|
||||
rpccmd.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
proxy.RootCmd,
|
||||
commands.VersionCmd,
|
||||
auto.AutoCompleteCmd,
|
||||
)
|
||||
|
||||
cmd := cli.PrepareMainCmd(BaseCli, "BC", os.ExpandEnv("$HOME/.basecli"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
client "github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/modules/auth"
|
||||
"github.com/cosmos/cosmos-sdk/modules/base"
|
||||
"github.com/cosmos/cosmos-sdk/modules/coin"
|
||||
"github.com/cosmos/cosmos-sdk/modules/eyes"
|
||||
"github.com/cosmos/cosmos-sdk/modules/fee"
|
||||
"github.com/cosmos/cosmos-sdk/modules/ibc"
|
||||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
"github.com/cosmos/cosmos-sdk/modules/roles"
|
||||
"github.com/cosmos/cosmos-sdk/server/commands"
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
)
|
||||
|
||||
// RootCmd is the entry point for this binary
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "basecoin",
|
||||
Short: "A cryptocurrency framework in Golang based on Tendermint-Core",
|
||||
}
|
||||
|
||||
// BuildApp constructs the stack we want to use for this app
|
||||
func BuildApp(feeDenom string) sdk.Handler {
|
||||
return stack.New(
|
||||
base.Logger{},
|
||||
stack.Recovery{},
|
||||
auth.Signatures{},
|
||||
base.Chain{},
|
||||
stack.Checkpoint{OnCheck: true},
|
||||
nonce.ReplayCheck{},
|
||||
).
|
||||
IBC(ibc.NewMiddleware()).
|
||||
Apps(
|
||||
roles.NewMiddleware(),
|
||||
fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank),
|
||||
stack.Checkpoint{OnDeliver: true},
|
||||
).
|
||||
Dispatch(
|
||||
coin.NewHandler(),
|
||||
stack.WrapHandler(roles.NewHandler()),
|
||||
stack.WrapHandler(ibc.NewHandler()),
|
||||
// and just for run, add eyes as well
|
||||
stack.WrapHandler(eyes.NewHandler()),
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// require all fees in mycoin - change this in your app!
|
||||
commands.Handler = BuildApp("mycoin")
|
||||
|
||||
RootCmd.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.StartCmd,
|
||||
//commands.RelayCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
client.VersionCmd,
|
||||
)
|
||||
commands.SetUpRoot(RootCmd)
|
||||
|
||||
cmd := cli.PrepareMainCmd(RootCmd, "BC", os.ExpandEnv("$HOME/.basecoin"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
# baseserver
|
||||
|
||||
baseserver is the REST counterpart to basecli
|
||||
|
||||
## Compiling and running it
|
||||
```shell
|
||||
$ go get -u -v github.com/tendermint/basecoin/cmd/baseserver
|
||||
$ baseserver init
|
||||
$ baseserver serve --port 8888
|
||||
```
|
||||
|
||||
to run the server at localhost:8888, otherwise if you don't specify --port,
|
||||
by default the server will be run on port 8998.
|
||||
|
||||
## Supported routes
|
||||
Route | Method | Completed | Description
|
||||
---|---|---|---
|
||||
/keys|GET|✔️|Lists all keys
|
||||
/keys|POST|✔️|Generate a new key. It expects fields: "name", "algo", "passphrase"
|
||||
/keys/{name}|GET|✔️|Retrieves the specific key
|
||||
/keys/{name}|POST/PUT|✔️|Updates the named key
|
||||
/keys/{name}|DELETE|✔️|Deletes the named key
|
||||
/build/send|POST|✔️|Send a transaction
|
||||
/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 $URL/keys --data '{"algo": "ed25519", "name": "SampleX", "passphrase": "Say no more"}'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"key": {
|
||||
"name": "SampleX",
|
||||
"address": "603EE63C41E322FC7A247864A9CD0181282EB458",
|
||||
"pubkey": {
|
||||
"type": "ed25519",
|
||||
"data": "C050948CFC087F5E1068C7E244DDC30E03702621CC9442A28E6C9EDA7771AA0C"
|
||||
}
|
||||
},
|
||||
"seed_phrase": "border almost future parade speak soccer bulk orange real brisk caution body river chapter"
|
||||
}
|
||||
```
|
||||
|
||||
- Sign a key
|
||||
```shell
|
||||
$ curl -X POST $URL/sign --data '{
|
||||
"name": "matt",
|
||||
"password": "Say no more",
|
||||
"tx": {
|
||||
"type": "sigs/multi",
|
||||
"data": {
|
||||
"tx": {"type":"coin/send","data":{"inputs":[{"address":{"chain":"","app":"role","addr":"62616E6B32"},"coins":[{"denom":"mycoin","amount":900000}]}],"outputs":[{"address":{"chain":"","app":"sigs","addr":"BDADF167E6CF2CDF2D621E590FF1FED2787A40E0"},"coins":[{"denom":"mycoin","amount":900000}]}]}},
|
||||
"signatures": null
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "sigs/multi",
|
||||
"data": {
|
||||
"tx": {
|
||||
"type": "coin/send",
|
||||
"data": {
|
||||
"inputs": [
|
||||
{
|
||||
"address": {
|
||||
"chain": "",
|
||||
"app": "role",
|
||||
"addr": "62616E6B32"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 900000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": {
|
||||
"chain": "",
|
||||
"app": "sigs",
|
||||
"addr": "BDADF167E6CF2CDF2D621E590FF1FED2787A40E0"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 900000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"signatures": [
|
||||
{
|
||||
"Sig": {
|
||||
"type": "ed25519",
|
||||
"data": "F6FE3053F1E6C236F886A0D525C1AF840F7831B6E50F7E1108C345AA524303920F09945DA110AD5184B3F45717D7114E368B12AFE027FECECC2FC193D4906A0C"
|
||||
},
|
||||
"Pubkey": {
|
||||
"type": "ed25519",
|
||||
"data": "0D8D19E527BAE9D1256A3D03009E2708171CDCB71CCDEDA2DC52DD9AD23AEE25"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,95 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
rest "github.com/cosmos/cosmos-sdk/client/rest"
|
||||
coinrest "github.com/cosmos/cosmos-sdk/modules/coin/rest"
|
||||
noncerest "github.com/cosmos/cosmos-sdk/modules/nonce/rest"
|
||||
rolerest "github.com/cosmos/cosmos-sdk/modules/roles/rest"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
)
|
||||
|
||||
var srvCli = &cobra.Command{
|
||||
Use: "baseserver",
|
||||
Short: "Light REST client for tendermint",
|
||||
Long: `Baseserver presents a nice (not raw hex) interface to the basecoin blockchain structure.`,
|
||||
}
|
||||
|
||||
var serveCmd = &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "Serve the light REST client for tendermint",
|
||||
Long: "Access basecoin via REST",
|
||||
RunE: serve,
|
||||
}
|
||||
|
||||
const (
|
||||
envPortFlag = "port"
|
||||
defaultAlgo = "ed25519"
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = serveCmd.PersistentFlags().Int(envPortFlag, 8998, "the port to run the server on")
|
||||
}
|
||||
|
||||
func serve(cmd *cobra.Command, args []string) error {
|
||||
router := mux.NewRouter()
|
||||
|
||||
routeRegistrars := []func(*mux.Router) error{
|
||||
// rest.Keys handlers
|
||||
rest.NewDefaultKeysManager(defaultAlgo).RegisterAllCRUD,
|
||||
|
||||
// Coin send handler
|
||||
coinrest.RegisterCoinSend,
|
||||
// Coin query account handler
|
||||
coinrest.RegisterQueryAccount,
|
||||
|
||||
// Roles createRole handler
|
||||
rolerest.RegisterCreateRole,
|
||||
|
||||
// Basecoin sign transactions handler
|
||||
rest.RegisterSignTx,
|
||||
// Basecoin post transaction handler
|
||||
rest.RegisterPostTx,
|
||||
|
||||
// Nonce query handler
|
||||
noncerest.RegisterQueryNonce,
|
||||
}
|
||||
|
||||
for _, routeRegistrar := range routeRegistrars {
|
||||
if err := routeRegistrar(router); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
port := viper.GetInt(envPortFlag)
|
||||
addr := fmt.Sprintf(":%d", port)
|
||||
|
||||
log.Printf("Serving on %q", addr)
|
||||
return http.ListenAndServe(addr, router)
|
||||
}
|
||||
|
||||
func main() {
|
||||
commands.AddBasicFlags(srvCli)
|
||||
|
||||
srvCli.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.VersionCmd,
|
||||
serveCmd,
|
||||
)
|
||||
|
||||
// this should share the dir with basecli, so you can use the cli and
|
||||
// the api interchangeably
|
||||
cmd := cli.PrepareMainCmd(srvCli, "BC", os.ExpandEnv("$HOME/.basecli"))
|
||||
if err := cmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/app"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/sendtx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
app := app.NewApp("basecoin")
|
||||
|
||||
db, err := dbm.NewGoLevelDB("basecoin", "basecoin-data")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// create CommitStoreLoader
|
||||
cacheSize := 10000
|
||||
numHistory := int64(100)
|
||||
loader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
||||
|
||||
// Create MultiStore
|
||||
multiStore := store.NewCommitMultiStore(db)
|
||||
multiStore.SetSubstoreLoader("main", loader)
|
||||
|
||||
// Create Handler
|
||||
handler := types.ChainDecorators(
|
||||
// recover.Decorator(),
|
||||
// logger.Decorator(),
|
||||
auth.DecoratorFn(newAccountStore),
|
||||
).WithHandler(
|
||||
sendtx.TransferHandlerFn(newAccountStore),
|
||||
)
|
||||
|
||||
// TODO: load genesis
|
||||
// TODO: InitChain with validators
|
||||
// accounts := newAccountStore(multiStore.GetKVStore("main"))
|
||||
// TODO: set the genesis accounts
|
||||
|
||||
// Set everything on the app and load latest
|
||||
app.SetCommitMultiStore(multiStore)
|
||||
app.SetTxParser(txParser)
|
||||
app.SetHandler(handler)
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Start the ABCI server
|
||||
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
srv.Start()
|
||||
|
||||
// Wait forever
|
||||
cmn.TrapSignal(func() {
|
||||
// Cleanup
|
||||
srv.Stop()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// create ctx in begin block to be used as background for txs ...
|
||||
|
||||
func txParser(txBytes []byte) (types.Tx, error) {
|
||||
var tx sendtx.SendTx
|
||||
err := json.Unmarshal(txBytes, &tx)
|
||||
return tx, err
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=basecoin
|
||||
CLIENT_EXE=basecli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
|
||||
oneTimeSetUp() {
|
||||
if ! quickSetup .basecoin_test_basictx basictx-chain; then
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
test00GetAccount() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
assertFalse "line=${LINENO}, requires arg" "${CLIENT_EXE} query account"
|
||||
|
||||
checkAccount $SENDER "9007199254740992"
|
||||
|
||||
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, has no genesis account" $?
|
||||
}
|
||||
|
||||
test01SendTx() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
assertFalse "line=${LINENO}, missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1"
|
||||
assertFalse "line=${LINENO}, bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH"
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkAccount $SENDER "9007199254740000" "$TX_HEIGHT"
|
||||
# make sure 0x prefix also works
|
||||
checkAccount "0x$SENDER" "9007199254740000" "$TX_HEIGHT"
|
||||
checkAccount $RECV "992" "$TX_HEIGHT"
|
||||
|
||||
# Make sure tx is indexed
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
|
||||
}
|
||||
|
||||
test02SendTxWithFee() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
# Test to see if the auto-sequencing works, the sequence here should be calculated to be 2
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=90mycoin --fee=10mycoin --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# deduct 100 from sender, add 90 to receiver... fees "vanish"
|
||||
checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
checkAccount $RECV "1082" "$TX_HEIGHT"
|
||||
|
||||
# Make sure tx is indexed
|
||||
checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10"
|
||||
|
||||
# assert replay protection
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=90mycoin --fee=10mycoin --sequence=2 --to=$RECV --name=$RICH 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, replay: $TX" $?
|
||||
|
||||
# checking normally
|
||||
checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
checkAccount $RECV "1082" "$TX_HEIGHT"
|
||||
|
||||
# make sure we can query the proper nonce
|
||||
NONCE=$(${CLIENT_EXE} query nonce $SENDER)
|
||||
if [ -n "$DEBUG" ]; then echo $NONCE; echo; fi
|
||||
# TODO: note that cobra returns error code 0 on parse failure,
|
||||
# so currently this check passes even if there is no nonce query command
|
||||
if assertTrue "line=${LINENO}, no nonce query" $?; then
|
||||
assertEquals "line=${LINENO}, proper nonce" "2" $(echo $NONCE | jq .data)
|
||||
fi
|
||||
|
||||
# make sure this works without trust also
|
||||
OLD_BC_HOME=$BC_HOME
|
||||
export BC_HOME=/foo
|
||||
export BC_TRUST_NODE=1
|
||||
export BC_NODE=localhost:46657
|
||||
checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10"
|
||||
checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
checkAccount $RECV "1082" "$TX_HEIGHT"
|
||||
unset BC_TRUST_NODE
|
||||
unset BC_NODE
|
||||
export BC_HOME=$OLD_BC_HOME
|
||||
}
|
||||
|
||||
|
||||
test03CreditTx() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
# make sure we are controlled by permissions (only rich can issue credit)
|
||||
assertFalse "line=${LINENO}, bad password" "echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=1000mycoin --sequence=1 --to=$RECV --name=$POOR"
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=1000mycoin --sequence=3 --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# receiver got cash, sender didn't lose any (1000 more than last check)
|
||||
checkAccount $RECV "2082" "$TX_HEIGHT"
|
||||
checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
}
|
||||
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,284 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=basecoin
|
||||
CLIENT_EXE=basecli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
|
||||
# For full stack traces in error output, run
|
||||
# BC_TRACE=1 ./ibc.sh
|
||||
|
||||
oneTimeSetUp() {
|
||||
# These are passed in as args
|
||||
BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1
|
||||
CHAIN_ID_1=test-chain-1
|
||||
CLIENT_1=${BASE_DIR_1}/client
|
||||
PREFIX_1=1234
|
||||
PORT_1=${PREFIX_1}7
|
||||
|
||||
BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2
|
||||
CHAIN_ID_2=test-chain-2
|
||||
CLIENT_2=${BASE_DIR_2}/client
|
||||
PREFIX_2=2345
|
||||
PORT_2=${PREFIX_2}7
|
||||
|
||||
# Clean up and create the test dirs
|
||||
rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null
|
||||
mkdir -p $BASE_DIR_1 $BASE_DIR_2
|
||||
|
||||
# Set up client for chain 1- make sure you use the proper prefix if you set
|
||||
# a custom CLIENT_EXE
|
||||
BC_HOME=${CLIENT_1} prepareClient
|
||||
BC_HOME=${CLIENT_2} prepareClient
|
||||
|
||||
# Start basecoin server, giving money to the key in the first client
|
||||
BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PREFIX_1
|
||||
if [ $? != 0 ]; then exit 1; fi
|
||||
PID_SERVER_1=$PID_SERVER
|
||||
|
||||
# Start second basecoin server, giving money to the key in the second client
|
||||
BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PREFIX_2
|
||||
if [ $? != 0 ]; then exit 1; fi
|
||||
PID_SERVER_2=$PID_SERVER
|
||||
|
||||
# Connect both clients
|
||||
BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 $PORT_1
|
||||
if [ $? != 0 ]; then exit 1; fi
|
||||
BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 $PORT_2
|
||||
if [ $? != 0 ]; then exit 1; fi
|
||||
|
||||
printf "...Testing may begin!\n\n\n"
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
printf "\n\nstopping both $SERVER_EXE test servers... $PID_SERVER_1 $PID_SERVER_2"
|
||||
kill -9 $PID_SERVER_1
|
||||
kill -9 $PID_SERVER_2
|
||||
sleep 1
|
||||
}
|
||||
|
||||
test00GetAccount() {
|
||||
export BC_HOME=${CLIENT_1}
|
||||
SENDER_1=$(getAddr $RICH)
|
||||
RECV_1=$(getAddr $POOR)
|
||||
|
||||
assertFalse "line=${LINENO}, requires arg" "${CLIENT_EXE} query account 2>/dev/null"
|
||||
assertFalse "line=${LINENO}, has no genesis account" "${CLIENT_EXE} query account $RECV_1 2>/dev/null"
|
||||
checkAccount $SENDER_1 "9007199254740992"
|
||||
|
||||
export BC_HOME=${CLIENT_2}
|
||||
SENDER_2=$(getAddr $RICH)
|
||||
RECV_2=$(getAddr $POOR)
|
||||
|
||||
assertFalse "line=${LINENO}, requires arg" "${CLIENT_EXE} query account 2>/dev/null"
|
||||
assertFalse "line=${LINENO}, has no genesis account" "${CLIENT_EXE} query account $RECV_2 2>/dev/null"
|
||||
checkAccount $SENDER_2 "9007199254740992"
|
||||
|
||||
# Make sure that they have different addresses on both chains (they are random keys)
|
||||
assertNotEquals "line=${LINENO}, sender keys must be different" "$SENDER_1" "$SENDER_2"
|
||||
assertNotEquals "line=${LINENO}, recipient keys must be different" "$RECV_1" "$RECV_2"
|
||||
}
|
||||
|
||||
test01RegisterChains() {
|
||||
# let's get the root commits to cross-register them
|
||||
ROOT_1="$BASE_DIR_1/root_commit.json"
|
||||
${CLIENT_EXE} commits export $ROOT_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
|
||||
ROOT_2="$BASE_DIR_2/root_commit.json"
|
||||
${CLIENT_EXE} commits export $ROOT_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
|
||||
# register chain2 on chain1
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \
|
||||
--sequence=1 --commit=${ROOT_2} --name=$POOR --home=${CLIENT_1})
|
||||
txSucceeded $? "$TX" "register chain2 on chain 1"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
# this is used later to check data
|
||||
REG_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# register chain1 on chain2 (no money needed... yet)
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \
|
||||
--sequence=1 --commit=${ROOT_1} --name=$POOR --home=${CLIENT_2})
|
||||
txSucceeded $? "$TX" "register chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
}
|
||||
|
||||
test02UpdateChains() {
|
||||
# let's get the root commits to cross-register them
|
||||
UPDATE_1="$BASE_DIR_1/seed_1.json"
|
||||
${CLIENT_EXE} commits update --home=${CLIENT_1} > /dev/null
|
||||
${CLIENT_EXE} commits export $UPDATE_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
# make sure it is newer than the other....
|
||||
assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1
|
||||
|
||||
UPDATE_2="$BASE_DIR_2/seed_2.json"
|
||||
${CLIENT_EXE} commits update --home=${CLIENT_2} > /dev/null
|
||||
${CLIENT_EXE} commits export $UPDATE_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2
|
||||
# this is used later to check query data
|
||||
REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .commit.header.height)
|
||||
UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .commit.header.height)
|
||||
|
||||
# update chain2 on chain1
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--sequence=2 --commit=${UPDATE_2} --name=$POOR --home=${CLIENT_1})
|
||||
txSucceeded $? "$TX" "update chain2 on chain 1"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
||||
# update chain1 on chain2 (no money needed... yet)
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--sequence=2 --commit=${UPDATE_1} --name=$POOR --home=${CLIENT_2})
|
||||
txSucceeded $? "$TX" "update chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
}
|
||||
|
||||
# make sure all query commands about ibc work...
|
||||
test03QueryIBC() {
|
||||
# just test on one chain, as they are all symetrical
|
||||
export BC_HOME=${CLIENT_1}
|
||||
|
||||
# make sure we can list all chains
|
||||
CHAINS=$(${CLIENT_EXE} query ibc chains)
|
||||
assertTrue "line=${LINENO}, cannot query chains" $?
|
||||
assertEquals "1" $(echo $CHAINS | jq '.data | length')
|
||||
assertEquals "line=${LINENO}" "\"$CHAIN_ID_2\"" $(echo $CHAINS | jq '.data[0]')
|
||||
|
||||
# error on unknown chain, data on proper chain
|
||||
assertFalse "line=${LINENO}, unknown chain" "${CLIENT_EXE} query ibc chain random 2>/dev/null"
|
||||
CHAIN_INFO=$(${CLIENT_EXE} query ibc chain $CHAIN_ID_2)
|
||||
assertTrue "line=${LINENO}, cannot query chain $CHAIN_ID_2" $?
|
||||
assertEquals "line=${LINENO}, register height" $REG_HEIGHT $(echo $CHAIN_INFO | jq .data.registered_at)
|
||||
assertEquals "line=${LINENO}, tracked height" $UPDATE_2_HEIGHT $(echo $CHAIN_INFO | jq .data.remote_block)
|
||||
}
|
||||
|
||||
# Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2
|
||||
# we make sure the money was reduced, but nothing arrived
|
||||
test04SendIBCPacket() {
|
||||
export BC_HOME=${CLIENT_1}
|
||||
|
||||
# make sure there are no packets yet
|
||||
PACKETS=$(${CLIENT_EXE} query ibc packets --to=$CHAIN_ID_2 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, packet query" $?
|
||||
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR)
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \
|
||||
--to=${CHAIN_ID_2}::${RECV} --name=$RICH)
|
||||
txSucceeded $? "$TX" "${CHAIN_ID_2}::${RECV}"
|
||||
# quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# Make sure balance went down and tx is indexed
|
||||
checkAccount $SENDER "9007199254720990" "$TX_HEIGHT"
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "20002"
|
||||
|
||||
# look, we wrote a packet
|
||||
PACKETS=$(${CLIENT_EXE} query ibc packets --to=$CHAIN_ID_2 --height=$TX_HEIGHT)
|
||||
assertTrue "line=${LINENO}, packets query" $?
|
||||
assertEquals "line=${LINENO}, packet count" 1 $(echo $PACKETS | jq .data)
|
||||
|
||||
# and look at the packet itself
|
||||
PACKET=$(${CLIENT_EXE} query ibc packet --to=$CHAIN_ID_2 --sequence=0 --height=$TX_HEIGHT)
|
||||
assertTrue "line=${LINENO}, packet query" $?
|
||||
assertEquals "line=${LINENO}, proper src" "\"$CHAIN_ID_1\"" $(echo $PACKET | jq .src_chain)
|
||||
assertEquals "line=${LINENO}, proper dest" "\"$CHAIN_ID_2\"" $(echo $PACKET | jq .packet.dest_chain)
|
||||
assertEquals "line=${LINENO}, proper sequence" "0" $(echo $PACKET | jq .packet.sequence)
|
||||
if [ -n "$DEBUG" ]; then echo $PACKET; echo; fi
|
||||
|
||||
# nothing arrived
|
||||
ARRIVED=$(${CLIENT_EXE} query ibc packets --from=$CHAIN_ID_1 --home=$CLIENT_2 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, packet query" $?
|
||||
assertFalse "line=${LINENO}, no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV"
|
||||
}
|
||||
|
||||
test05ReceiveIBCPacket() {
|
||||
export BC_HOME=${CLIENT_2}
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
# make some credit, so we can accept the packet
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx credit --amount=60006mycoin --to=$CHAIN_ID_1:: --name=$RICH)
|
||||
txSucceeded $? "$TX" "${CHAIN_ID_1}::"
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# make sure there is enough credit
|
||||
checkAccount $CHAIN_ID_1:: "60006" "$TX_HEIGHT"
|
||||
# and the poor guy doesn't have a penny to his name
|
||||
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, has no genesis account" $?
|
||||
|
||||
|
||||
# now, we try to post it.... (this is PACKET from last test)
|
||||
|
||||
# get the commit with the proof and post it
|
||||
SRC_HEIGHT=$(echo $PACKET | jq .src_height)
|
||||
PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1)
|
||||
# FIXME: this should auto-update on proofs...
|
||||
${CLIENT_EXE} commits update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null
|
||||
assertTrue "line=${LINENO}, update commit failed" $?
|
||||
|
||||
PACKET_COMMIT="$BASE_DIR_1/packet_commit.json"
|
||||
${CLIENT_EXE} commits export $PACKET_COMMIT --home=${CLIENT_1} --height=$PROOF_HEIGHT
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
if [ -n "$DEBUG" ]; then
|
||||
echo "**** SEED ****"
|
||||
cat $PACKET_COMMIT | jq .commit.header
|
||||
echo
|
||||
fi
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--commit=${PACKET_COMMIT} --name=$POOR --sequence=3)
|
||||
txSucceeded $? "$TX" "prepare packet chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# write the packet to the file
|
||||
POST_PACKET="$BASE_DIR_1/post_packet.json"
|
||||
echo $PACKET > $POST_PACKET
|
||||
|
||||
# post it as a tx (cross-fingers)
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-post \
|
||||
--packet=${POST_PACKET} --name=$POOR --sequence=4)
|
||||
txSucceeded $? "$TX" "post packet from chain1 on chain 2"
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# ensure $POOR balance was incremented, and credit for CHAIN_1 decremented
|
||||
checkAccount $CHAIN_ID_1:: "40004" "$TX_HEIGHT"
|
||||
checkAccount $RECV "20002" "$TX_HEIGHT"
|
||||
|
||||
# look, we wrote a packet
|
||||
PACKETS=$(${CLIENT_EXE} query ibc packets --height=$TX_HEIGHT --from=$CHAIN_ID_1)
|
||||
assertTrue "line=${LINENO}, packets query" $?
|
||||
assertEquals "line=${LINENO}, packet count" 1 $(echo $PACKETS | jq .data)
|
||||
}
|
||||
|
||||
# XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2
|
||||
# Desc: Asserts that seed2 has a higher block height than commit 1
|
||||
assertNewHeight() {
|
||||
H1=$(cat $2 | jq .commit.header.height)
|
||||
H2=$(cat $3 | jq .commit.header.height)
|
||||
assertTrue "$1" "test $H2 -gt $H1"
|
||||
return $?
|
||||
}
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CLIENT_EXE=basecli
|
||||
SERVER_EXE=basecoin
|
||||
|
||||
test01initOption() {
|
||||
BASE=~/.bc_init_test
|
||||
rm -rf "$BASE"
|
||||
mkdir -p "$BASE"
|
||||
|
||||
SERVE_DIR="${BASE}/server"
|
||||
GENESIS_FILE=${SERVE_DIR}/genesis.json
|
||||
HEX="deadbeef1234deadbeef1234deadbeef1234aaaa"
|
||||
|
||||
${SERVER_EXE} init ${HEX} --home="$SERVE_DIR" -p=eyes/key1/val1 -p='"eyes/key2/{""name"": ""joe"", ""age"": ""100""}"' >/dev/null
|
||||
if ! assertTrue "line=${LINENO}" $?; then return 1; fi
|
||||
|
||||
OPTION1KEY=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[2]')
|
||||
OPTION1VAL=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[3]')
|
||||
OPTION2KEY=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[4]')
|
||||
OPTION2VAL=$(cat ${GENESIS_FILE} | jq '.app_options.plugin_options[5]')
|
||||
OPTION2VALEXPECTED=$(echo '{"name": "joe", "age": "100"}' | jq '.')
|
||||
|
||||
assertEquals "line=${LINENO}" '"eyes/key1"' $OPTION1KEY
|
||||
assertEquals "line=${LINENO}" '"val1"' $OPTION1VAL
|
||||
assertEquals "line=${LINENO}" '"eyes/key2"' $OPTION2KEY
|
||||
assertEquals "line=${LINENO}" "$OPTION2VALEXPECTED" "$OPTION2VAL"
|
||||
}
|
||||
|
||||
test02runServer() {
|
||||
# Attempt to begin the server with the custom genesis
|
||||
SERVER_LOG=$BASE/${SERVER_EXE}.log
|
||||
startServer $SERVE_DIR $SERVER_LOG
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
# load and run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,110 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CLIENT_EXE=basecli
|
||||
SERVER_EXE=basecoin
|
||||
|
||||
oneTimeSetUp() {
|
||||
BASE=~/.bc_init_test
|
||||
rm -rf "$BASE"
|
||||
mkdir -p "$BASE"
|
||||
|
||||
SERVER="${BASE}/server"
|
||||
SERVER_LOG="${BASE}/${SERVER_EXE}.log"
|
||||
|
||||
HEX="deadbeef1234deadbeef1234deadbeef1234aaaa"
|
||||
${SERVER_EXE} init ${HEX} --home="$SERVER" >> "$SERVER_LOG"
|
||||
if ! assertTrue "line=${LINENO}" $?; then return 1; fi
|
||||
|
||||
GENESIS_FILE=${SERVER}/genesis.json
|
||||
CHAIN_ID=$(cat ${GENESIS_FILE} | jq .chain_id | tr -d \")
|
||||
|
||||
printf "starting ${SERVER_EXE}...\n"
|
||||
${SERVER_EXE} start --home="$SERVER" >> "$SERVER_LOG" 2>&1 &
|
||||
sleep 5
|
||||
PID_SERVER=$!
|
||||
disown
|
||||
if ! ps $PID_SERVER >/dev/null; then
|
||||
echo "**STARTUP FAILED**"
|
||||
cat $SERVER_LOG
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
printf "\nstopping ${SERVER_EXE}..."
|
||||
kill -9 $PID_SERVER >/dev/null 2>&1
|
||||
sleep 1
|
||||
}
|
||||
|
||||
test01goodInit() {
|
||||
export BCHOME=${BASE}/client-01
|
||||
assertFalse "line=${LINENO}" "ls ${BCHOME} 2>/dev/null >&2"
|
||||
|
||||
echo y | ${CLIENT_EXE} init --node=tcp://localhost:46657 --chain-id="${CHAIN_ID}" > /dev/null
|
||||
assertTrue "line=${LINENO}, initialized light-client" $?
|
||||
checkDir $BCHOME 3
|
||||
}
|
||||
|
||||
test02badInit() {
|
||||
export BCHOME=${BASE}/client-02
|
||||
assertFalse "line=${LINENO}" "ls ${BCHOME} 2>/dev/null >&2"
|
||||
|
||||
# no node where we go
|
||||
echo y | ${CLIENT_EXE} init --node=tcp://localhost:9999 --chain-id="${CHAIN_ID}" > /dev/null 2>&1
|
||||
assertFalse "line=${LINENO}, invalid init" $?
|
||||
# dir there, but empty...
|
||||
checkDir $BCHOME 0
|
||||
|
||||
# try with invalid chain id
|
||||
echo y | ${CLIENT_EXE} init --node=tcp://localhost:46657 --chain-id="bad-chain-id" > /dev/null 2>&1
|
||||
assertFalse "line=${LINENO}, invalid init" $?
|
||||
checkDir $BCHOME 0
|
||||
|
||||
# reject the response
|
||||
echo n | ${CLIENT_EXE} init --node=tcp://localhost:46657 --chain-id="${CHAIN_ID}" > /dev/null 2>&1
|
||||
assertFalse "line=${LINENO}, invalid init" $?
|
||||
checkDir $BCHOME 0
|
||||
}
|
||||
|
||||
test03noDoubleInit() {
|
||||
export BCHOME=${BASE}/client-03
|
||||
assertFalse "line=${LINENO}" "ls ${BCHOME} 2>/dev/null >&2"
|
||||
|
||||
# init properly
|
||||
echo y | ${CLIENT_EXE} init --node=tcp://localhost:46657 --chain-id="${CHAIN_ID}" > /dev/null 2>&1
|
||||
assertTrue "line=${LINENO}, initialized light-client" $?
|
||||
checkDir $BCHOME 3
|
||||
|
||||
# try again, and we get an error
|
||||
echo y | ${CLIENT_EXE} init --node=tcp://localhost:46657 --chain-id="${CHAIN_ID}" > /dev/null 2>&1
|
||||
assertFalse "line=${LINENO}, warning on re-init" $?
|
||||
checkDir $BCHOME 3
|
||||
|
||||
# unless we --force-reset
|
||||
echo y | ${CLIENT_EXE} init --force-reset --node=tcp://localhost:46657 --chain-id="${CHAIN_ID}" > /dev/null 2>&1
|
||||
assertTrue "line=${LINENO}, re-initialized light-client" $?
|
||||
checkDir $BCHOME 3
|
||||
}
|
||||
|
||||
test04acceptGenesisFile() {
|
||||
export BCHOME=${BASE}/client-04
|
||||
assertFalse "line=${LINENO}" "ls ${BCHOME} 2>/dev/null >&2"
|
||||
|
||||
# init properly
|
||||
${CLIENT_EXE} init --node=tcp://localhost:46657 --genesis=${GENESIS_FILE} > /dev/null 2>&1
|
||||
assertTrue "line=${LINENO}, initialized light-client" $?
|
||||
checkDir $BCHOME 3
|
||||
}
|
||||
|
||||
# XXX Ex: checkDir $DIR $FILES
|
||||
# Makes sure directory exists and has the given number of files
|
||||
checkDir() {
|
||||
assertTrue "line=${LINENO}" "ls ${1} 2>/dev/null >&2"
|
||||
assertEquals "line=${LINENO}, no files created" "$2" $(ls $1 | wc -l)
|
||||
}
|
||||
|
||||
# load and run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,146 +0,0 @@
|
||||
#!/bin/bash
|
||||
EXE=basecli
|
||||
|
||||
|
||||
oneTimeSetUp() {
|
||||
PASS=qwertyuiop
|
||||
export BCHOME=$HOME/.bc_keys_test
|
||||
${EXE} reset_all
|
||||
assertTrue "line ${LINENO}" $?
|
||||
}
|
||||
|
||||
newKey(){
|
||||
assertNotNull "keyname required" "$1"
|
||||
KEYPASS=${2:-qwertyuiop}
|
||||
KEY=$(echo $KEYPASS | ${EXE} keys new $1 -o json)
|
||||
if ! assertTrue "line ${LINENO}: created $1" $?; then return 1; fi
|
||||
assertEquals "$1" $(echo $KEY | jq .key.name | tr -d \")
|
||||
return $?
|
||||
}
|
||||
|
||||
# updateKey <name> <oldkey> <newkey>
|
||||
updateKey() {
|
||||
(echo $2; echo $3) | ${EXE} keys update $1 > /dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
test00MakeKeys() {
|
||||
USER=demouser
|
||||
assertFalse "line ${LINENO}: already user $USER" "${EXE} keys get $USER"
|
||||
newKey $USER
|
||||
assertTrue "line ${LINENO}: no user $USER" "${EXE} keys get $USER"
|
||||
# make sure bad password not accepted
|
||||
assertFalse "accepts short password" "echo 123 | ${EXE} keys new badpass"
|
||||
}
|
||||
|
||||
test01ListKeys() {
|
||||
# one line plus the number of keys
|
||||
assertEquals "2" $(${EXE} keys list | wc -l)
|
||||
newKey foobar
|
||||
assertEquals "3" $(${EXE} keys list | wc -l)
|
||||
# we got the proper name here...
|
||||
assertEquals "foobar" $(${EXE} keys list -o json | jq .[1].name | tr -d \" )
|
||||
# we get all names in normal output
|
||||
EXPECTEDNAMES=$(echo demouser; echo foobar)
|
||||
TEXTNAMES=$(${EXE} keys list | tail -n +2 | cut -f1)
|
||||
assertEquals "$EXPECTEDNAMES" "$TEXTNAMES"
|
||||
# let's make sure the addresses match!
|
||||
assertEquals "line ${LINENO}: text and json addresses don't match" $(${EXE} keys list | tail -1 | cut -f3) $(${EXE} keys list -o json | jq .[1].address | tr -d \")
|
||||
}
|
||||
|
||||
test02updateKeys() {
|
||||
USER=changer
|
||||
PASS1=awsedrftgyhu
|
||||
PASS2=S4H.9j.D9S7hso
|
||||
PASS3=h8ybO7GY6d2
|
||||
|
||||
newKey $USER $PASS1
|
||||
assertFalse "line ${LINENO}: accepts invalid pass" "updateKey $USER $PASS2 $PASS2"
|
||||
assertTrue "line ${LINENO}: doesn't update" "updateKey $USER $PASS1 $PASS2"
|
||||
assertTrue "line ${LINENO}: takes new key after update" "updateKey $USER $PASS2 $PASS3"
|
||||
}
|
||||
|
||||
test03recoverKeys() {
|
||||
USER=sleepy
|
||||
PASS1=S4H.9j.D9S7hso
|
||||
|
||||
USER2=easy
|
||||
PASS2=1234567890
|
||||
|
||||
# make a user and check they exist
|
||||
KEY=$(echo $PASS1 | ${EXE} keys new $USER -o json)
|
||||
if ! assertTrue "created $USER" $?; then return 1; fi
|
||||
if [ -n "$DEBUG" ]; then echo $KEY; echo; fi
|
||||
|
||||
SEED=$(echo $KEY | jq .seed | tr -d \")
|
||||
ADDR=$(echo $KEY | jq .key.address | tr -d \")
|
||||
PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \")
|
||||
assertTrue "line ${LINENO}" "${EXE} keys get $USER > /dev/null"
|
||||
|
||||
# let's delete this key
|
||||
assertFalse "line ${LINENO}" "echo foo | ${EXE} keys delete $USER > /dev/null"
|
||||
assertTrue "line ${LINENO}" "echo $PASS1 | ${EXE} keys delete $USER > /dev/null"
|
||||
assertFalse "line ${LINENO}" "${EXE} keys get $USER > /dev/null"
|
||||
|
||||
# fails on short password
|
||||
assertFalse "line ${LINENO}" "echo foo; echo $SEED | ${EXE} keys recover $USER2 -o json > /dev/null"
|
||||
# fails on bad seed
|
||||
assertFalse "line ${LINENO}" "echo $PASS2; echo \"silly white whale tower bongo\" | ${EXE} keys recover $USER2 -o json > /dev/null"
|
||||
# now we got it
|
||||
KEY2=$((echo $PASS2; echo $SEED) | ${EXE} keys recover $USER2 -o json)
|
||||
if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi
|
||||
if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi
|
||||
|
||||
# make sure it looks the same
|
||||
NAME2=$(echo $KEY2 | jq .name | tr -d \")
|
||||
ADDR2=$(echo $KEY2 | jq .address | tr -d \")
|
||||
PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \")
|
||||
assertEquals "line ${LINENO}: wrong username" "$USER2" "$NAME2"
|
||||
assertEquals "line ${LINENO}: address doesn't match" "$ADDR" "$ADDR2"
|
||||
assertEquals "line ${LINENO}: pubkey doesn't match" "$PUBKEY" "$PUBKEY2"
|
||||
|
||||
# and we can find the info
|
||||
assertTrue "line ${LINENO}" "${EXE} keys get $USER2 > /dev/null"
|
||||
}
|
||||
|
||||
# try recovery with secp256k1 keys
|
||||
test03recoverSecp() {
|
||||
USER=dings
|
||||
PASS1=Sbub-U9byS7hso
|
||||
|
||||
USER2=booms
|
||||
PASS2=1234567890
|
||||
|
||||
KEY=$(echo $PASS1 | ${EXE} keys new $USER -o json -t secp256k1)
|
||||
if ! assertTrue "created $USER" $?; then return 1; fi
|
||||
if [ -n "$DEBUG" ]; then echo $KEY; echo; fi
|
||||
|
||||
SEED=$(echo $KEY | jq .seed | tr -d \")
|
||||
ADDR=$(echo $KEY | jq .key.address | tr -d \")
|
||||
PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \")
|
||||
assertTrue "line ${LINENO}" "${EXE} keys get $USER > /dev/null"
|
||||
|
||||
# now we got it
|
||||
KEY2=$((echo $PASS2; echo $SEED) | ${EXE} keys recover $USER2 -o json)
|
||||
if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi
|
||||
if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi
|
||||
|
||||
# make sure it looks the same
|
||||
NAME2=$(echo $KEY2 | jq .name | tr -d \")
|
||||
ADDR2=$(echo $KEY2 | jq .address | tr -d \")
|
||||
PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \")
|
||||
assertEquals "line ${LINENO}: wrong username" "$USER2" "$NAME2"
|
||||
assertEquals "line ${LINENO}: address doesn't match" "$ADDR" "$ADDR2"
|
||||
assertEquals "line ${LINENO}: pubkey doesn't match" "$PUBKEY" "$PUBKEY2"
|
||||
|
||||
# and we can find the info
|
||||
assertTrue "line ${LINENO}" "${EXE} keys get $USER2 > /dev/null"
|
||||
}
|
||||
|
||||
# load and run these tests with shunit2!
|
||||
|
||||
# load and run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,161 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=basecoin
|
||||
CLIENT_EXE=basecli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
|
||||
BPORT=7000
|
||||
URL="localhost:${BPORT}"
|
||||
|
||||
oneTimeSetUp() {
|
||||
if ! quickSetup .basecoin_test_rest rest-chain; then
|
||||
exit 1;
|
||||
fi
|
||||
baseserver serve --port $BPORT >/dev/null &
|
||||
sleep 0.1 # for startup
|
||||
PID_PROXY=$!
|
||||
disown
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
kill -9 $PID_PROXY
|
||||
}
|
||||
|
||||
# XXX Ex Usage: restAddr $NAME
|
||||
# Desc: Gets the address for a key name via rest
|
||||
restAddr() {
|
||||
assertNotNull "line=${LINENO}, keyname required" "$1"
|
||||
ADDR=$(curl ${URL}/keys/${1} 2>/dev/null | jq .address | tr -d \")
|
||||
assertNotEquals "line=${LINENO}, null key" "null" "$ADDR"
|
||||
assertNotEquals "line=${LINENO}, no key" "" "$ADDR"
|
||||
echo $ADDR
|
||||
}
|
||||
|
||||
# XXX Ex Usage: restAccount $ADDR $AMOUNT [$HEIGHT]
|
||||
# Desc: Assumes just one coin, checks the balance of first coin in any case
|
||||
restAccount() {
|
||||
assertNotNull "line=${LINENO}, address required" "$1"
|
||||
QUERY=${URL}/query/account/sigs:$1
|
||||
if [ -n "$3" ]; then
|
||||
QUERY="${QUERY}?height=${3}"
|
||||
fi
|
||||
ACCT=$(curl ${QUERY} 2>/dev/null)
|
||||
if [ -n "$DEBUG" ]; then echo $QUERY; echo $ACCT; echo; fi
|
||||
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" 400 $(echo $ERROR | jq .code)
|
||||
}
|
||||
|
||||
test00GetAccount() {
|
||||
RECV=$(restAddr $POOR)
|
||||
SENDER=$(restAddr $RICH)
|
||||
|
||||
restNoAccount $RECV
|
||||
restAccount $SENDER "9007199254740992"
|
||||
}
|
||||
|
||||
test01SendTx() {
|
||||
SENDER=$(restAddr $RICH)
|
||||
RECV=$(restAddr $POOR)
|
||||
|
||||
CMD="{\"from\": {\"app\": \"sigs\", \"addr\": \"$SENDER\"}, \"to\": {\"app\": \"sigs\", \"addr\": \"$RECV\"}, \"amount\": [{\"denom\": \"mycoin\", \"amount\": 992}], \"sequence\": 1}"
|
||||
|
||||
UNSIGNED=$(curl -XPOST ${URL}/build/send -d "$CMD" 2>/dev/null)
|
||||
if [ -n "$DEBUG" ]; then echo $UNSIGNED; echo; fi
|
||||
|
||||
TOSIGN="{\"name\": \"$RICH\", \"password\": \"qwertyuiop\", \"tx\": $UNSIGNED}"
|
||||
SIGNED=$(curl -XPOST ${URL}/sign -d "$TOSIGN" 2>/dev/null)
|
||||
TX=$(curl -XPOST ${URL}/tx -d "$SIGNED" 2>/dev/null)
|
||||
if [ -n "$DEBUG" ]; then echo $TX; echo; fi
|
||||
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
restAccount $SENDER "9007199254740000" "$TX_HEIGHT"
|
||||
restAccount $RECV "992" "$TX_HEIGHT"
|
||||
|
||||
# Make sure tx is indexed
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
|
||||
}
|
||||
|
||||
|
||||
# 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)
|
||||
}
|
||||
|
||||
|
||||
# test02SendTxWithFee() {
|
||||
# SENDER=$(getAddr $RICH)
|
||||
# RECV=$(getAddr $POOR)
|
||||
|
||||
# # Test to see if the auto-sequencing works, the sequence here should be calculated to be 2
|
||||
# TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=90mycoin --fee=10mycoin --to=$RECV --name=$RICH)
|
||||
# txSucceeded $? "$TX" "$RECV"
|
||||
# HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
# TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# # deduct 100 from sender, add 90 to receiver... fees "vanish"
|
||||
# checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
# checkAccount $RECV "1082" "$TX_HEIGHT"
|
||||
|
||||
# # Make sure tx is indexed
|
||||
# checkSendFeeTx $HASH $TX_HEIGHT $SENDER "90" "10"
|
||||
|
||||
# # assert replay protection
|
||||
# TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=90mycoin --fee=10mycoin --sequence=2 --to=$RECV --name=$RICH 2>/dev/null)
|
||||
# assertFalse "line=${LINENO}, replay: $TX" $?
|
||||
# checkAccount $SENDER "9007199254739900" "$TX_HEIGHT"
|
||||
# checkAccount $RECV "1082" "$TX_HEIGHT"
|
||||
|
||||
# # make sure we can query the proper nonce
|
||||
# NONCE=$(${CLIENT_EXE} query nonce $SENDER)
|
||||
# if [ -n "$DEBUG" ]; then echo $NONCE; echo; fi
|
||||
# # TODO: note that cobra returns error code 0 on parse failure,
|
||||
# # so currently this check passes even if there is no nonce query command
|
||||
# if assertTrue "line=${LINENO}, no nonce query" $?; then
|
||||
# assertEquals "line=${LINENO}, proper nonce" "2" $(echo $NONCE | jq .data)
|
||||
# fi
|
||||
# }
|
||||
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# these are two globals to control all scripts (can use eg. counter instead)
|
||||
SERVER_EXE=basecoin
|
||||
CLIENT_EXE=basecli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
|
||||
oneTimeSetUp() {
|
||||
if ! quickSetup .basecoin_test_restart restart-chain; then
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
test00PreRestart() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkAccount $SENDER "9007199254740000" "$TX_HEIGHT"
|
||||
checkAccount $RECV "992" "$TX_HEIGHT"
|
||||
|
||||
# make sure tx is indexed
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
|
||||
|
||||
}
|
||||
|
||||
test01OnRestart() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=10000mycoin --sequence=2 --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
if [ $? != 0 ]; then echo "can't make tx!"; return 1; fi
|
||||
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# wait til we have quite a few blocks... like at least 20,
|
||||
# so the query command won't just wait for the next eg. 7 blocks to verify the result
|
||||
echo "waiting to generate lots of blocks..."
|
||||
sleep 5
|
||||
echo "done waiting!"
|
||||
|
||||
# last minute tx just at the block cut-off...
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20000mycoin --sequence=3 --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
if [ $? != 0 ]; then echo "can't make second tx!"; return 1; fi
|
||||
|
||||
# now we do a restart...
|
||||
quickTearDown
|
||||
startServer $BASE_DIR/server $BASE_DIR/${SERVER_EXE}.log
|
||||
if [ $? != 0 ]; then echo "can't restart server!"; return 1; fi
|
||||
|
||||
# make sure queries still work properly, with all 3 tx now executed
|
||||
echo "Checking state after restart..."
|
||||
checkAccount $SENDER "9007199254710000"
|
||||
checkAccount $RECV "30992"
|
||||
|
||||
# make sure tx is indexed
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "10000"
|
||||
|
||||
# for double-check of logs
|
||||
if [ -n "$DEBUG" ]; then
|
||||
cat $BASE_DIR/${SERVER_EXE}.log;
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=basecoin
|
||||
CLIENT_EXE=basecli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
DUDE=${ACCOUNTS[2]}
|
||||
ROLE="10CAFE4E"
|
||||
|
||||
oneTimeSetUp() {
|
||||
if ! quickSetup .basecoin_test_roles roles-chain; then
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
test01SetupRole() {
|
||||
ONE=$(getAddr $RICH)
|
||||
TWO=$(getAddr $POOR)
|
||||
THREE=$(getAddr $DUDE)
|
||||
MEMBERS=${ONE},${TWO},${THREE}
|
||||
|
||||
SIGS=2
|
||||
|
||||
assertFalse "line=${LINENO}, missing min-sigs" "echo qwertyuiop | ${CLIENT_EXE} tx create-role --role=${ROLE} --members=${MEMBERS} --sequence=1 --name=$RICH"
|
||||
assertFalse "line=${LINENO}, missing members" "echo qwertyuiop | ${CLIENT_EXE} tx create-role --role=${ROLE} --min-sigs=2 --sequence=1 --name=$RICH"
|
||||
assertFalse "line=${LINENO}, missing role" "echo qwertyuiop | ${CLIENT_EXE} tx create-role --min-sigs=2 --members=${MEMBERS} --sequence=1 --name=$RICH"
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx create-role --role=${ROLE} --min-sigs=$SIGS --members=${MEMBERS} --sequence=1 --name=$RICH)
|
||||
txSucceeded $? "$TX" "${ROLE}"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkRole "${ROLE}" $SIGS 3 "$TX_HEIGHT"
|
||||
|
||||
# Make sure tx is indexed
|
||||
checkRoleTx $HASH $TX_HEIGHT "${ROLE}" 3
|
||||
}
|
||||
|
||||
test02SendTxToRole() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=role:${ROLE}
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --fee=90mycoin --amount=10000mycoin --to=$RECV --sequence=2 --name=$RICH)
|
||||
txSucceeded $? "$TX" "${ROLE}"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# reduce by 10090
|
||||
checkAccount $SENDER "9007199254730902" "$TX_HEIGHT"
|
||||
checkAccount $RECV "10000" "$TX_HEIGHT"
|
||||
|
||||
checkSendFeeTx $HASH $TX_HEIGHT $SENDER "10000" "90"
|
||||
}
|
||||
|
||||
test03SendMultiFromRole() {
|
||||
ONE=$(getAddr $RICH)
|
||||
TWO=$(getAddr $POOR)
|
||||
THREE=$(getAddr $DUDE)
|
||||
BANK=role:${ROLE}
|
||||
|
||||
# no money to start mr. poor...
|
||||
assertFalse "line=${LINENO}, has no money yet" "${CLIENT_EXE} query account $TWO 2>/dev/null"
|
||||
|
||||
# let's try to send money from the role directly without multisig
|
||||
FAIL=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=6000mycoin --from=$BANK --to=$TWO --sequence=1 --name=$POOR 2>/dev/null)
|
||||
assertFalse "need to assume role" $?
|
||||
FAIL=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=6000mycoin --from=$BANK --to=$TWO --sequence=2 --assume-role=${ROLE} --name=$POOR 2>/dev/null)
|
||||
assertFalse "need two signatures" $?
|
||||
|
||||
# okay, begin a multisig transaction mr. poor...
|
||||
TX_FILE=$BASE_DIR/tx.json
|
||||
echo qwertyuiop | ${CLIENT_EXE} tx send --amount=6000mycoin --from=$BANK --to=$TWO --sequence=1 --assume-role=${ROLE} --name=$POOR --multi --prepare=$TX_FILE
|
||||
assertTrue "line=${LINENO}, successfully prepare tx" $?
|
||||
# and get some dude to sign it
|
||||
# FAIL=$(echo qwertyuiop | ${CLIENT_EXE} tx --in=$TX_FILE --name=$POOR 2>/dev/null)
|
||||
# assertFalse "line=${LINENO}, double signing doesn't get bank" $?
|
||||
# and get some dude to sign it for the full access
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx --in=$TX_FILE --name=$DUDE)
|
||||
txSucceeded $? "$TX" "multi-bank"
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkAccount $TWO "6000" "$TX_HEIGHT"
|
||||
checkAccount $BANK "4000" "$TX_HEIGHT"
|
||||
}
|
||||
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,132 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CLIENT_EXE=basecli
|
||||
SERVER_EXE=basecoin
|
||||
|
||||
oneTimeSetUp() {
|
||||
BASE=~/.bc_init_test
|
||||
rm -rf "$BASE"
|
||||
mkdir -p "$BASE"
|
||||
|
||||
SERVER="${BASE}/server"
|
||||
SERVER_LOG="${BASE}/${SERVER_EXE}.log"
|
||||
|
||||
HEX="deadbeef1234deadbeef1234deadbeef1234aaaa"
|
||||
${SERVER_EXE} init ${HEX} --home="$SERVER" >> "$SERVER_LOG"
|
||||
if ! assertTrue "line=${LINENO}" $?; then return 1; fi
|
||||
|
||||
GENESIS_FILE=${SERVER}/genesis.json
|
||||
CHAIN_ID=$(cat ${GENESIS_FILE} | jq .chain_id | tr -d \")
|
||||
|
||||
printf "starting ${SERVER_EXE}...\n"
|
||||
${SERVER_EXE} start --home="$SERVER" >> "$SERVER_LOG" 2>&1 &
|
||||
sleep 5
|
||||
PID_SERVER=$!
|
||||
disown
|
||||
if ! ps $PID_SERVER >/dev/null; then
|
||||
echo "**STARTUP FAILED**"
|
||||
cat $SERVER_LOG
|
||||
return 1
|
||||
fi
|
||||
|
||||
# this sets the base for all client queries in the tests
|
||||
export BCHOME=${BASE}/client
|
||||
${CLIENT_EXE} init --node=tcp://localhost:46657 --genesis=${GENESIS_FILE} > /dev/null 2>&1
|
||||
if ! assertTrue "line=${LINENO}, initialized light-client" "$?"; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
printf "\nstopping ${SERVER_EXE}..."
|
||||
kill -9 $PID_SERVER >/dev/null 2>&1
|
||||
sleep 1
|
||||
}
|
||||
|
||||
test01GetInsecure() {
|
||||
GENESIS=$(${CLIENT_EXE} rpc genesis)
|
||||
assertTrue "line=${LINENO}, get genesis" "$?"
|
||||
MYCHAIN=$(echo ${GENESIS} | jq .genesis.chain_id | tr -d \")
|
||||
assertEquals "line=${LINENO}, genesis chain matches" "${CHAIN_ID}" "${MYCHAIN}"
|
||||
|
||||
STATUS=$(${CLIENT_EXE} rpc status)
|
||||
assertTrue "line=${LINENO}, get status" "$?"
|
||||
SHEIGHT=$(echo ${STATUS} | jq .latest_block_height)
|
||||
assertTrue "line=${LINENO}, parsed status" "$?"
|
||||
assertNotNull "line=${LINENO}, has a height" "${SHEIGHT}"
|
||||
|
||||
VALS=$(${CLIENT_EXE} rpc validators)
|
||||
assertTrue "line=${LINENO}, get validators" "$?"
|
||||
VHEIGHT=$(echo ${VALS} | jq .block_height)
|
||||
assertTrue "line=${LINENO}, parsed validators" "$?"
|
||||
assertTrue "line=${LINENO}, sensible heights: $SHEIGHT / $VHEIGHT" "test $VHEIGHT -ge $SHEIGHT"
|
||||
VCNT=$(echo ${VALS} | jq '.validators | length')
|
||||
assertEquals "line=${LINENO}, one validator" "1" "$VCNT"
|
||||
|
||||
INFO=$(${CLIENT_EXE} rpc info)
|
||||
assertTrue "line=${LINENO}, get info" "$?"
|
||||
DATA=$(echo $INFO | jq .response.data)
|
||||
assertEquals "line=${LINENO}, basecoin info" '"basecoin v0.7.1"' "$DATA"
|
||||
}
|
||||
|
||||
test02GetSecure() {
|
||||
HEIGHT=$(${CLIENT_EXE} rpc status | jq .latest_block_height)
|
||||
assertTrue "line=${LINENO}, get status" "$?"
|
||||
|
||||
# check block produces something reasonable
|
||||
assertFalse "line=${LINENO}, missing height" "${CLIENT_EXE} rpc block"
|
||||
BLOCK=$(${CLIENT_EXE} rpc block --height=$HEIGHT)
|
||||
assertTrue "line=${LINENO}, get block" "$?"
|
||||
MHEIGHT=$(echo $BLOCK | jq .block_meta.header.height)
|
||||
assertEquals "line=${LINENO}, meta height" "${HEIGHT}" "${MHEIGHT}"
|
||||
BHEIGHT=$(echo $BLOCK | jq .block.header.height)
|
||||
assertEquals "line=${LINENO}, meta height" "${HEIGHT}" "${BHEIGHT}"
|
||||
|
||||
# check commit produces something reasonable
|
||||
assertFalse "line=${LINENO}, missing height" "${CLIENT_EXE} rpc commit"
|
||||
let "CHEIGHT = $HEIGHT - 1"
|
||||
COMMIT=$(${CLIENT_EXE} rpc commit --height=$CHEIGHT)
|
||||
assertTrue "line=${LINENO}, get commit" "$?"
|
||||
HHEIGHT=$(echo $COMMIT | jq .header.height)
|
||||
assertEquals "line=${LINENO}, commit height" "${CHEIGHT}" "${HHEIGHT}"
|
||||
assertEquals "line=${LINENO}, canonical" "true" $(echo $COMMIT | jq .canonical)
|
||||
BSIG=$(echo $BLOCK | jq .block.last_commit)
|
||||
CSIG=$(echo $COMMIT | jq .commit)
|
||||
assertEquals "line=${LINENO}, block and commit" "$BSIG" "$CSIG"
|
||||
|
||||
# now let's get some headers
|
||||
# assertFalse "missing height" "${CLIENT_EXE} rpc headers"
|
||||
HEADERS=$(${CLIENT_EXE} rpc headers --min=$CHEIGHT --max=$HEIGHT)
|
||||
assertTrue "line=${LINENO}, get headers" "$?"
|
||||
assertEquals "line=${LINENO}, proper height" "$HEIGHT" $(echo $HEADERS | jq '.block_metas[0].header.height')
|
||||
assertEquals "line=${LINENO}, two headers" "2" $(echo $HEADERS | jq '.block_metas | length')
|
||||
# should we check these headers?
|
||||
CHEAD=$(echo $COMMIT | jq .header)
|
||||
# most recent first, so the commit header is second....
|
||||
HHEAD=$(echo $HEADERS | jq .block_metas[1].header)
|
||||
assertEquals "line=${LINENO}, commit and header" "$CHEAD" "$HHEAD"
|
||||
}
|
||||
|
||||
test03Waiting() {
|
||||
START=$(${CLIENT_EXE} rpc status | jq .latest_block_height)
|
||||
assertTrue "line=${LINENO}, get status" "$?"
|
||||
|
||||
let "NEXT = $START + 5"
|
||||
assertFalse "line=${LINENO}, no args" "${CLIENT_EXE} rpc wait"
|
||||
assertFalse "line=${LINENO}, too long" "${CLIENT_EXE} rpc wait --height=1234"
|
||||
assertTrue "line=${LINENO}, normal wait" "${CLIENT_EXE} rpc wait --height=$NEXT"
|
||||
|
||||
STEP=$(${CLIENT_EXE} rpc status | jq .latest_block_height)
|
||||
assertEquals "line=${LINENO}, wait until height" "$NEXT" "$STEP"
|
||||
|
||||
let "NEXT = $STEP + 3"
|
||||
assertTrue "line=${LINENO}, ${CLIENT_EXE} rpc wait --delta=3"
|
||||
STEP=$(${CLIENT_EXE} rpc status | jq .latest_block_height)
|
||||
assertEquals "line=${LINENO}, wait for delta" "$NEXT" "$STEP"
|
||||
}
|
||||
|
||||
# load and run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -1,14 +0,0 @@
|
||||
LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`"
|
||||
|
||||
install:
|
||||
@go install -ldflags $(LINKER_FLAGS) ./cmd/...
|
||||
|
||||
test: test_unit test_cli
|
||||
|
||||
test_unit:
|
||||
@go test `glide novendor`
|
||||
|
||||
test_cli:
|
||||
./tests/cli/counter.sh
|
||||
|
||||
.PHONY: install test test_unit test_cli
|
||||
@@ -1,36 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
client "github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/examples/counter/plugins/counter"
|
||||
"github.com/cosmos/cosmos-sdk/server/commands"
|
||||
)
|
||||
|
||||
// RootCmd is the entry point for this binary
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "counter",
|
||||
Short: "demo application for cosmos sdk",
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// TODO: register the counter here
|
||||
commands.Handler = counter.NewHandler("mycoin")
|
||||
|
||||
RootCmd.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.StartCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
client.VersionCmd,
|
||||
)
|
||||
commands.SetUpRoot(RootCmd)
|
||||
|
||||
cmd := cli.PrepareMainCmd(RootCmd, "CT", os.ExpandEnv("$HOME/.counter"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
"github.com/cosmos/cosmos-sdk/examples/counter/plugins/counter"
|
||||
"github.com/cosmos/cosmos-sdk/modules/coin"
|
||||
)
|
||||
|
||||
//CounterTxCmd is the CLI command to execute the counter
|
||||
// through the appTx Command
|
||||
var CounterTxCmd = &cobra.Command{
|
||||
Use: "counter",
|
||||
Short: "add a vote to the counter",
|
||||
Long: `Add a vote to the counter.
|
||||
|
||||
You must pass --valid for it to count and the countfee will be added to the counter.`,
|
||||
RunE: counterTx,
|
||||
}
|
||||
|
||||
// nolint - flags names
|
||||
const (
|
||||
FlagCountFee = "countfee"
|
||||
FlagValid = "valid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fs := CounterTxCmd.Flags()
|
||||
fs.String(FlagCountFee, "", "Coins to send in the format <amt><coin>,<amt><coin>...")
|
||||
fs.Bool(FlagValid, false, "Is count valid?")
|
||||
}
|
||||
|
||||
func counterTx(cmd *cobra.Command, args []string) error {
|
||||
tx, err := readCounterTxFlags()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return txcmd.DoTx(tx)
|
||||
}
|
||||
|
||||
func readCounterTxFlags() (tx sdk.Tx, err error) {
|
||||
feeCoins, err := coin.ParseCoins(viper.GetString(FlagCountFee))
|
||||
if err != nil {
|
||||
return tx, err
|
||||
}
|
||||
|
||||
tx = counter.NewTx(viper.GetBool(FlagValid), feeCoins)
|
||||
return tx, nil
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/counter/plugins/counter"
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
)
|
||||
|
||||
//CounterQueryCmd - CLI command to query the counter state
|
||||
var CounterQueryCmd = &cobra.Command{
|
||||
Use: "counter",
|
||||
Short: "Query counter state, with proof",
|
||||
RunE: counterQueryCmd,
|
||||
}
|
||||
|
||||
func counterQueryCmd(cmd *cobra.Command, args []string) error {
|
||||
var cp counter.State
|
||||
|
||||
prove := !viper.GetBool(commands.FlagTrustNode)
|
||||
key := stack.PrefixedKey(counter.NameCounter, counter.StateKey())
|
||||
h, err := query.GetParsed(key, &cp, query.GetHeight(), prove)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return query.OutputProof(cp, h)
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/proxy"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
bcount "github.com/cosmos/cosmos-sdk/examples/counter/cmd/countercli/commands"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands"
|
||||
basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands"
|
||||
coincmd "github.com/cosmos/cosmos-sdk/modules/coin/commands"
|
||||
feecmd "github.com/cosmos/cosmos-sdk/modules/fee/commands"
|
||||
noncecmd "github.com/cosmos/cosmos-sdk/modules/nonce/commands"
|
||||
)
|
||||
|
||||
// CounterCli represents the base command when called without any subcommands
|
||||
var CounterCli = &cobra.Command{
|
||||
Use: "countercli",
|
||||
Short: "Example app built using the Cosmos SDK",
|
||||
Long: `Countercli is a demo app that includes custom logic to
|
||||
present a formatted interface to a custom blockchain structure.
|
||||
|
||||
This is a useful tool and also serves to demonstrate how to configure
|
||||
the Cosmos SDK to work for any custom ABCI app, see:
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
func main() {
|
||||
commands.AddBasicFlags(CounterCli)
|
||||
|
||||
// Prepare queries
|
||||
query.RootCmd.AddCommand(
|
||||
// These are default parsers, optional in your app
|
||||
query.TxQueryCmd,
|
||||
query.KeyQueryCmd,
|
||||
coincmd.AccountQueryCmd,
|
||||
noncecmd.NonceQueryCmd,
|
||||
|
||||
// XXX IMPORTANT: here is how you add custom query commands in your app
|
||||
bcount.CounterQueryCmd,
|
||||
)
|
||||
|
||||
// set up the middleware
|
||||
txcmd.Middleware = txcmd.Wrappers{
|
||||
feecmd.FeeWrapper{},
|
||||
noncecmd.NonceWrapper{},
|
||||
basecmd.ChainWrapper{},
|
||||
authcmd.SigWrapper{},
|
||||
}
|
||||
txcmd.Middleware.Register(txcmd.RootCmd.PersistentFlags())
|
||||
|
||||
// Prepare transactions
|
||||
txcmd.RootCmd.AddCommand(
|
||||
// This is the default transaction, optional in your app
|
||||
coincmd.SendTxCmd,
|
||||
|
||||
// XXX IMPORTANT: here is how you add custom tx construction for your app
|
||||
bcount.CounterTxCmd,
|
||||
)
|
||||
|
||||
// Set up the various commands to use
|
||||
CounterCli.AddCommand(
|
||||
commands.InitCmd,
|
||||
commands.ResetCmd,
|
||||
commands.VersionCmd,
|
||||
keys.RootCmd,
|
||||
commits.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
proxy.RootCmd,
|
||||
)
|
||||
|
||||
cmd := cli.PrepareMainCmd(CounterCli, "CTL", os.ExpandEnv("$HOME/.countercli"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
package counter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-wire"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/errors"
|
||||
"github.com/cosmos/cosmos-sdk/modules/auth"
|
||||
"github.com/cosmos/cosmos-sdk/modules/base"
|
||||
"github.com/cosmos/cosmos-sdk/modules/coin"
|
||||
"github.com/cosmos/cosmos-sdk/modules/fee"
|
||||
"github.com/cosmos/cosmos-sdk/modules/ibc"
|
||||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
"github.com/cosmos/cosmos-sdk/modules/roles"
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
"github.com/cosmos/cosmos-sdk/state"
|
||||
)
|
||||
|
||||
// Tx
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// register the tx type with it's validation logic
|
||||
// make sure to use the name of the handler as the prefix in the tx type,
|
||||
// so it gets routed properly
|
||||
const (
|
||||
NameCounter = "cntr"
|
||||
ByteTx = 0x2F //TODO What does this byte represent should use typebytes probably
|
||||
TypeTx = NameCounter + "/count"
|
||||
)
|
||||
|
||||
func init() {
|
||||
sdk.TxMapper.RegisterImplementation(Tx{}, TypeTx, ByteTx)
|
||||
}
|
||||
|
||||
// Tx - struct for all counter transactions
|
||||
type Tx struct {
|
||||
Valid bool `json:"valid"`
|
||||
Fee coin.Coins `json:"fee"`
|
||||
}
|
||||
|
||||
// NewTx - return a new counter transaction struct wrapped as a basecoin transaction
|
||||
func NewTx(valid bool, fee coin.Coins) sdk.Tx {
|
||||
return Tx{
|
||||
Valid: valid,
|
||||
Fee: fee,
|
||||
}.Wrap()
|
||||
}
|
||||
|
||||
// Wrap - Wrap a Tx as a Basecoin Tx, used to satisfy the XXX interface
|
||||
func (c Tx) Wrap() sdk.Tx {
|
||||
return sdk.Tx{TxInner: c}
|
||||
}
|
||||
|
||||
// ValidateBasic just makes sure the Fee is a valid, non-negative value
|
||||
func (c Tx) ValidateBasic() error {
|
||||
if !c.Fee.IsValid() {
|
||||
return coin.ErrInvalidCoins()
|
||||
}
|
||||
if !c.Fee.IsNonnegative() {
|
||||
return coin.ErrInvalidCoins()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Custom errors
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
var (
|
||||
errInvalidCounter = fmt.Errorf("Counter Tx marked invalid")
|
||||
)
|
||||
|
||||
// ErrInvalidCounter - custom error class
|
||||
func ErrInvalidCounter() error {
|
||||
return errors.WithCode(errInvalidCounter, abci.CodeType_BaseInvalidInput)
|
||||
}
|
||||
|
||||
// IsInvalidCounterErr - custom error class check
|
||||
func IsInvalidCounterErr(err error) bool {
|
||||
return errors.IsSameError(errInvalidCounter, err)
|
||||
}
|
||||
|
||||
// ErrDecoding - This is just a helper function to return a generic "internal error"
|
||||
func ErrDecoding() error {
|
||||
return errors.ErrInternal("Error decoding state")
|
||||
}
|
||||
|
||||
// Counter Handler
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// NewHandler returns a new counter transaction processing handler
|
||||
func NewHandler(feeDenom string) sdk.Handler {
|
||||
return stack.New(
|
||||
base.Logger{},
|
||||
stack.Recovery{},
|
||||
auth.Signatures{},
|
||||
base.Chain{},
|
||||
stack.Checkpoint{OnCheck: true},
|
||||
nonce.ReplayCheck{},
|
||||
).
|
||||
IBC(ibc.NewMiddleware()).
|
||||
Apps(
|
||||
roles.NewMiddleware(),
|
||||
fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank),
|
||||
stack.Checkpoint{OnDeliver: true},
|
||||
).
|
||||
Dispatch(
|
||||
coin.NewHandler(),
|
||||
Handler{},
|
||||
)
|
||||
}
|
||||
|
||||
// Handler the counter transaction processing handler
|
||||
type Handler struct {
|
||||
stack.PassInitState
|
||||
stack.PassInitValidate
|
||||
}
|
||||
|
||||
var _ stack.Dispatchable = Handler{}
|
||||
|
||||
// Name - return counter namespace
|
||||
func (Handler) Name() string {
|
||||
return NameCounter
|
||||
}
|
||||
|
||||
// AssertDispatcher - placeholder to satisfy XXX
|
||||
func (Handler) AssertDispatcher() {}
|
||||
|
||||
// CheckTx checks if the tx is properly structured
|
||||
func (h Handler) CheckTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx, _ sdk.Checker) (res sdk.CheckResult, err error) {
|
||||
_, err = checkTx(ctx, tx)
|
||||
return
|
||||
}
|
||||
|
||||
// DeliverTx executes the tx if valid
|
||||
func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx, dispatch sdk.Deliver) (res sdk.DeliverResult, err error) {
|
||||
ctr, err := checkTx(ctx, tx)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// note that we don't assert this on CheckTx (ValidateBasic),
|
||||
// as we allow them to be writen to the chain
|
||||
if !ctr.Valid {
|
||||
return res, ErrInvalidCounter()
|
||||
}
|
||||
|
||||
// handle coin movement.... like, actually decrement the other account
|
||||
if !ctr.Fee.IsZero() {
|
||||
// take the coins and put them in out account!
|
||||
senders := ctx.GetPermissions("", auth.NameSigs)
|
||||
if len(senders) == 0 {
|
||||
return res, errors.ErrMissingSignature()
|
||||
}
|
||||
in := []coin.TxInput{{Address: senders[0], Coins: ctr.Fee}}
|
||||
out := []coin.TxOutput{{Address: StoreActor(), Coins: ctr.Fee}}
|
||||
send := coin.NewSendTx(in, out)
|
||||
// if the deduction fails (too high), abort the command
|
||||
_, err = dispatch.DeliverTx(ctx, store, send)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
// update the counter
|
||||
state, err := LoadState(store)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
state.Counter++
|
||||
state.TotalFees = state.TotalFees.Plus(ctr.Fee)
|
||||
err = SaveState(store, state)
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
func checkTx(ctx sdk.Context, tx sdk.Tx) (ctr Tx, err error) {
|
||||
ctr, ok := tx.Unwrap().(Tx)
|
||||
if !ok {
|
||||
return ctr, errors.ErrInvalidFormat(TypeTx, tx)
|
||||
}
|
||||
err = ctr.ValidateBasic()
|
||||
if err != nil {
|
||||
return ctr, err
|
||||
}
|
||||
return ctr, nil
|
||||
}
|
||||
|
||||
// CounterStore
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// StoreActor - return the basecoin actor for the account
|
||||
func StoreActor() sdk.Actor {
|
||||
return sdk.Actor{App: NameCounter, Address: []byte{0x04, 0x20}} //XXX what do these bytes represent? - should use typebyte variables
|
||||
}
|
||||
|
||||
// State - state of the counter applicaton
|
||||
type State struct {
|
||||
Counter int `json:"counter"`
|
||||
TotalFees coin.Coins `json:"total_fees"`
|
||||
}
|
||||
|
||||
// StateKey - store key for the counter state
|
||||
func StateKey() []byte {
|
||||
return []byte("state")
|
||||
}
|
||||
|
||||
// LoadState - retrieve the counter state from the store
|
||||
func LoadState(store state.SimpleDB) (state State, err error) {
|
||||
bytes := store.Get(StateKey())
|
||||
if len(bytes) > 0 {
|
||||
err = wire.ReadBinaryBytes(bytes, &state)
|
||||
if err != nil {
|
||||
return state, errors.ErrDecoding()
|
||||
}
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// SaveState - save the counter state to the provided store
|
||||
func SaveState(store state.SimpleDB, state State) error {
|
||||
bytes := wire.BinaryBytes(state)
|
||||
store.Set(StateKey(), bytes)
|
||||
return nil
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package counter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/app"
|
||||
"github.com/cosmos/cosmos-sdk/modules/auth"
|
||||
"github.com/cosmos/cosmos-sdk/modules/base"
|
||||
"github.com/cosmos/cosmos-sdk/modules/coin"
|
||||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
)
|
||||
|
||||
func TestCounterPlugin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
// Basecoin initialization
|
||||
chainID := "test_chain_id"
|
||||
logger := log.TestingLogger()
|
||||
// logger := log.NewTracingLogger(log.NewTMLogger(os.Stdout))
|
||||
|
||||
h := NewHandler("gold")
|
||||
store, err := app.MockStoreApp("counter", logger)
|
||||
require.Nil(err, "%+v", err)
|
||||
bcApp := app.NewBaseApp(store, h, nil)
|
||||
err = bcApp.InitState("base", "chain_id", chainID)
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
// Account initialization
|
||||
bal := coin.Coins{{"", 1000}, {"gold", 1000}}
|
||||
acct := coin.NewAccountWithKey(bal)
|
||||
err = bcApp.InitState("coin", "account", acct.MakeOption())
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
// Deliver a CounterTx
|
||||
DeliverCounterTx := func(valid bool, counterFee coin.Coins, sequence uint32) abci.Result {
|
||||
tx := NewTx(valid, counterFee)
|
||||
tx = nonce.NewTx(sequence, []sdk.Actor{acct.Actor()}, tx)
|
||||
tx = base.NewChainTx(chainID, 0, tx)
|
||||
stx := auth.NewSig(tx)
|
||||
auth.Sign(stx, acct.Key)
|
||||
txBytes := wire.BinaryBytes(stx.Wrap())
|
||||
return bcApp.DeliverTx(txBytes)
|
||||
}
|
||||
|
||||
// Test a basic send, no fee
|
||||
res := DeliverCounterTx(true, nil, 1)
|
||||
assert.True(res.IsOK(), res.String())
|
||||
|
||||
// Test an invalid send, no fee
|
||||
res = DeliverCounterTx(false, nil, 2)
|
||||
assert.True(res.IsErr(), res.String())
|
||||
|
||||
// Test an invalid sequence
|
||||
res = DeliverCounterTx(true, nil, 2)
|
||||
assert.True(res.IsErr(), res.String())
|
||||
|
||||
// Test an valid send, with supported fee
|
||||
res = DeliverCounterTx(true, coin.Coins{{"gold", 100}}, 3)
|
||||
assert.True(res.IsOK(), res.String())
|
||||
|
||||
// Test unsupported fee
|
||||
res = DeliverCounterTx(true, coin.Coins{{"silver", 100}}, 4)
|
||||
assert.True(res.IsErr(), res.String())
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=counter
|
||||
CLIENT_EXE=countercli
|
||||
ACCOUNTS=(jae ethan bucky rigel igor)
|
||||
RICH=${ACCOUNTS[0]}
|
||||
POOR=${ACCOUNTS[4]}
|
||||
|
||||
oneTimeSetUp() {
|
||||
if ! quickSetup .basecoin_test_counter counter-chain; then
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
test00GetAccount() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
assertFalse "Line=${LINENO}, requires arg" "${CLIENT_EXE} query account"
|
||||
|
||||
checkAccount $SENDER "9007199254740992"
|
||||
|
||||
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
|
||||
assertFalse "Line=${LINENO}, has no genesis account" $?
|
||||
}
|
||||
|
||||
test01SendTx() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
RECV=$(getAddr $POOR)
|
||||
|
||||
# sequence should work well for first time also
|
||||
assertFalse "Line=${LINENO}, missing dest" "${CLIENT_EXE} tx send --amount=992mycoin 2>/dev/null"
|
||||
assertFalse "Line=${LINENO}, bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --to=$RECV --name=$RICH 2>/dev/null"
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --to=$RECV --name=$RICH)
|
||||
txSucceeded $? "$TX" "$RECV"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkAccount $SENDER "9007199254740000" "$TX_HEIGHT"
|
||||
checkAccount $RECV "992" "$TX_HEIGHT"
|
||||
|
||||
# make sure tx is indexed
|
||||
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
|
||||
}
|
||||
|
||||
test02GetCounter() {
|
||||
COUNT=$(${CLIENT_EXE} query counter 2>/dev/null)
|
||||
assertFalse "Line=${LINENO}, no default count" $?
|
||||
}
|
||||
|
||||
# checkCounter $COUNT $BALANCE [$HEIGHT]
|
||||
# Assumes just one coin, checks the balance of first coin in any case
|
||||
# pass optional height to query which block to query
|
||||
checkCounter() {
|
||||
# default height of 0, but accept an argument
|
||||
HEIGHT=${3:-0}
|
||||
|
||||
# make sure sender goes down
|
||||
ACCT=$(${CLIENT_EXE} query counter --height=$HEIGHT)
|
||||
if assertTrue "Line=${LINENO}, count is set" $?; then
|
||||
assertEquals "Line=${LINENO}, proper count" "$1" $(echo $ACCT | jq .data.counter)
|
||||
assertEquals "Line=${LINENO}, proper money" "$2" $(echo $ACCT | jq .data.total_fees[0].amount)
|
||||
fi
|
||||
}
|
||||
|
||||
test03AddCount() {
|
||||
SENDER=$(getAddr $RICH)
|
||||
assertFalse "Line=${LINENO}, bad password" "echo hi | ${CLIENT_EXE} tx counter --countfee=100mycoin --sequence=2 --name=${RICH} 2>/dev/null"
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=10mycoin --sequence=2 --name=${RICH} --valid)
|
||||
txSucceeded $? "$TX" "counter"
|
||||
HASH=$(echo $TX | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# make sure the counter was updated
|
||||
checkCounter "1" "10" "$TX_HEIGHT"
|
||||
|
||||
# make sure the account was debited
|
||||
checkAccount $SENDER "9007199254739990" "$TX_HEIGHT"
|
||||
|
||||
# make sure tx is indexed
|
||||
TX=$(${CLIENT_EXE} query tx $HASH --trace)
|
||||
if assertTrue "Line=${LINENO}, found tx" $?; then
|
||||
assertEquals "Line=${LINENO}, proper height" $TX_HEIGHT $(echo $TX | jq .height)
|
||||
assertEquals "Line=${LINENO}, type=sigs/one" '"sigs/one"' $(echo $TX | jq .data.type)
|
||||
CTX=$(echo $TX | jq .data.data.tx)
|
||||
assertEquals "Line=${LINENO}, type=chain/tx" '"chain/tx"' $(echo $CTX | jq .type)
|
||||
NTX=$(echo $CTX | jq .data.tx)
|
||||
assertEquals "line=${LINENO}, type=nonce" '"nonce"' $(echo $NTX | jq .type)
|
||||
CNTX=$(echo $NTX | jq .data.tx)
|
||||
assertEquals "Line=${LINENO}, type=cntr/count" '"cntr/count"' $(echo $CNTX | jq .type)
|
||||
assertEquals "Line=${LINENO}, proper fee" "10" $(echo $CNTX | jq .data.fee[0].amount)
|
||||
fi
|
||||
|
||||
# test again with fees...
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=7mycoin --fee=4mycoin --sequence=3 --name=${RICH} --valid)
|
||||
txSucceeded $? "$TX" "counter"
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
# make sure the counter was updated, added 7
|
||||
checkCounter "2" "17" "$TX_HEIGHT"
|
||||
# make sure the account was debited 11
|
||||
checkAccount $SENDER "9007199254739979" "$TX_HEIGHT"
|
||||
|
||||
# make sure we cannot replay the counter, no state change
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=10mycoin --sequence=2 --name=${RICH} --valid 2>/dev/null)
|
||||
assertFalse "line=${LINENO}, replay: $TX" $?
|
||||
TX_HEIGHT=$(echo $TX | jq .height)
|
||||
|
||||
checkCounter "2" "17" "$TX_HEIGHT"
|
||||
checkAccount $SENDER "9007199254739979" "$TX_HEIGHT"
|
||||
}
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
@@ -0,0 +1,136 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/app"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
app := app.NewApp("dummy")
|
||||
|
||||
db, err := dbm.NewGoLevelDB("dummy", "dummy-data")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// create CommitStoreLoader
|
||||
cacheSize := 10000
|
||||
numHistory := int64(100)
|
||||
loader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
||||
|
||||
// Create MultiStore
|
||||
multiStore := store.NewCommitMultiStore(db)
|
||||
multiStore.SetSubstoreLoader("main", loader)
|
||||
|
||||
// Create Handler
|
||||
handler := types.Decorate(unmarshalDecorator, dummyHandler)
|
||||
|
||||
// Set everything on the app and load latest
|
||||
app.SetCommitMultiStore(multiStore)
|
||||
app.SetHandler(handler)
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Start the ABCI server
|
||||
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
srv.Start()
|
||||
|
||||
// Wait forever
|
||||
cmn.TrapSignal(func() {
|
||||
// Cleanup
|
||||
srv.Stop()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
type dummyTx struct {
|
||||
key []byte
|
||||
value []byte
|
||||
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
func (tx dummyTx) Get(key interface{}) (value interface{}) {
|
||||
switch k := key.(type) {
|
||||
case string:
|
||||
switch k {
|
||||
case "key":
|
||||
return tx.key
|
||||
case "value":
|
||||
return tx.value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx dummyTx) SignBytes() []byte {
|
||||
return tx.bytes
|
||||
}
|
||||
|
||||
// Should the app be calling this? Or only handlers?
|
||||
func (tx dummyTx) ValidateBasic() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx dummyTx) Signers() []types.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx dummyTx) TxBytes() []byte {
|
||||
return tx.bytes
|
||||
}
|
||||
|
||||
func (tx dummyTx) Signatures() []types.StdSignature {
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmarshalDecorator(ctx types.Context, ms types.MultiStore, tx types.Tx, next types.Handler) types.Result {
|
||||
txBytes := ctx.TxBytes()
|
||||
|
||||
split := bytes.Split(txBytes, []byte("="))
|
||||
if len(split) == 1 {
|
||||
k := split[0]
|
||||
tx = dummyTx{k, k, txBytes}
|
||||
} else if len(split) == 2 {
|
||||
k, v := split[0], split[1]
|
||||
tx = dummyTx{k, v, txBytes}
|
||||
} else {
|
||||
return types.Result{
|
||||
Code: 1,
|
||||
Log: "too many =",
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, ms, tx)
|
||||
}
|
||||
|
||||
func dummyHandler(ctx types.Context, ms types.MultiStore, tx types.Tx) types.Result {
|
||||
// tx is already unmarshalled
|
||||
key := tx.Get("key").([]byte)
|
||||
value := tx.Get("value").([]byte)
|
||||
|
||||
main := ms.GetKVStore("main")
|
||||
main.Set(key, value)
|
||||
|
||||
return types.Result{
|
||||
Code: 0,
|
||||
Log: fmt.Sprintf("set %s=%s", key, value),
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
LINKER_FLAGS:="-X github.com/cosmos/cosmos-sdk/client/commands.CommitHash=`git rev-parse --short HEAD`"
|
||||
|
||||
install:
|
||||
@go install -ldflags $(LINKER_FLAGS) ./cmd/...
|
||||
|
||||
test: test_unit test_cli
|
||||
|
||||
test_unit:
|
||||
@go test `glide novendor`
|
||||
|
||||
test_cli:
|
||||
./tests/cli/eyes.sh
|
||||
|
||||
.PHONY: install test test_unit test_cli
|
||||
@@ -1,58 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server/commands"
|
||||
)
|
||||
|
||||
// InitCmd - node initialization command
|
||||
var InitCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize eyes abci server",
|
||||
RunE: initCmd,
|
||||
}
|
||||
|
||||
//nolint - flags
|
||||
var (
|
||||
FlagChainID = "chain-id" //TODO group with other flags or remove? is this already a flag here?
|
||||
)
|
||||
|
||||
func init() {
|
||||
InitCmd.Flags().String(FlagChainID, "eyes_test_id", "Chain ID")
|
||||
}
|
||||
|
||||
func initCmd(cmd *cobra.Command, args []string) error {
|
||||
// this will ensure that config.toml is there if not yet created, and create dir
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genesis := getGenesisJSON(viper.GetString(commands.FlagChainID))
|
||||
return commands.CreateGenesisValidatorFiles(cfg, genesis, commands.StaticPrivValJSON, cmd.Root().Name())
|
||||
}
|
||||
|
||||
// TODO: better, auto-generate validator...
|
||||
func getGenesisJSON(chainID string) string {
|
||||
return fmt.Sprintf(`{
|
||||
"app_hash": "",
|
||||
"chain_id": "%s",
|
||||
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||
"validators": [
|
||||
{
|
||||
"power": 10,
|
||||
"name": "",
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
|
||||
}
|
||||
}
|
||||
]
|
||||
}`, chainID)
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
client "github.com/cosmos/cosmos-sdk/client/commands"
|
||||
eyesmod "github.com/cosmos/cosmos-sdk/modules/eyes"
|
||||
"github.com/cosmos/cosmos-sdk/server/commands"
|
||||
"github.com/cosmos/cosmos-sdk/util"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/eyes"
|
||||
)
|
||||
|
||||
// RootCmd is the entry point for this binary
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "eyes",
|
||||
Short: "key-value store",
|
||||
Long: "A demo app to show key-value store with proofs over abci",
|
||||
}
|
||||
|
||||
// BuildApp constructs the stack we want to use for this app
|
||||
func BuildApp() sdk.Handler {
|
||||
return sdk.ChainDecorators(
|
||||
util.Logger{},
|
||||
util.Recovery{},
|
||||
eyes.Parser{},
|
||||
util.Chain{},
|
||||
).WithHandler(
|
||||
eyesmod.NewHandler(),
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
commands.Handler = BuildApp()
|
||||
|
||||
RootCmd.AddCommand(
|
||||
// out own init command to not require argument
|
||||
InitCmd,
|
||||
commands.StartCmd,
|
||||
commands.UnsafeResetAllCmd,
|
||||
client.VersionCmd,
|
||||
)
|
||||
commands.SetUpRoot(RootCmd)
|
||||
|
||||
cmd := cli.PrepareMainCmd(RootCmd, "EYE", os.ExpandEnv("$HOME/.eyes"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/auto"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc"
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
eyescmd "github.com/cosmos/cosmos-sdk/modules/eyes/commands"
|
||||
)
|
||||
|
||||
// EyesCli - main basecoin client command
|
||||
var EyesCli = &cobra.Command{
|
||||
Use: "eyescli",
|
||||
Short: "Light client for Tendermint",
|
||||
Long: `EyesCli is the light client for a merkle key-value store (eyes)`,
|
||||
}
|
||||
|
||||
func main() {
|
||||
commands.AddBasicFlags(EyesCli)
|
||||
|
||||
// Prepare queries
|
||||
query.RootCmd.AddCommand(
|
||||
// These are default parsers, but optional in your app (you can remove key)
|
||||
query.TxQueryCmd,
|
||||
query.KeyQueryCmd,
|
||||
// this is our custom parser
|
||||
eyescmd.EyesQueryCmd,
|
||||
)
|
||||
|
||||
// no middleware wrapers
|
||||
txcmd.Middleware = txcmd.Wrappers{}
|
||||
// txcmd.Middleware.Register(txcmd.RootCmd.PersistentFlags())
|
||||
|
||||
// just the etc commands
|
||||
txcmd.RootCmd.AddCommand(
|
||||
eyescmd.SetTxCmd,
|
||||
eyescmd.RemoveTxCmd,
|
||||
)
|
||||
|
||||
// Set up the various commands to use
|
||||
EyesCli.AddCommand(
|
||||
// we use out own init command to not require address arg
|
||||
commands.InitCmd,
|
||||
commands.ResetCmd,
|
||||
commits.RootCmd,
|
||||
rpccmd.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
commands.VersionCmd,
|
||||
auto.AutoCompleteCmd,
|
||||
)
|
||||
|
||||
cmd := cli.PrepareMainCmd(EyesCli, "EYE", os.ExpandEnv("$HOME/.eyescli"))
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package eyes
|
||||
|
||||
import sdk "github.com/cosmos/cosmos-sdk"
|
||||
|
||||
// Parser converts bytes into a tx struct
|
||||
type Parser struct{}
|
||||
|
||||
var _ sdk.Decorator = Parser{}
|
||||
|
||||
// CheckTx makes sure we are on the proper chain
|
||||
// - fulfills Decorator interface
|
||||
func (c Parser) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
|
||||
txBytes interface{}, next sdk.Checker) (res sdk.CheckResult, err error) {
|
||||
|
||||
tx, err := LoadTx(txBytes.([]byte))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return next.CheckTx(ctx, store, tx)
|
||||
}
|
||||
|
||||
// DeliverTx makes sure we are on the proper chain
|
||||
// - fulfills Decorator interface
|
||||
func (c Parser) DeliverTx(ctx sdk.Context, store sdk.SimpleDB,
|
||||
txBytes interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) {
|
||||
|
||||
tx, err := LoadTx(txBytes.([]byte))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return next.DeliverTx(ctx, store, tx)
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# These global variables are required for common.sh
|
||||
SERVER_EXE=eyes
|
||||
CLIENT_EXE=eyescli
|
||||
|
||||
oneTimeSetUp() {
|
||||
# These are passed in as args
|
||||
BASE_DIR=$HOME/.test_eyes
|
||||
CHAIN_ID="eyes-cli-test"
|
||||
|
||||
rm -rf $BASE_DIR 2>/dev/null
|
||||
mkdir -p $BASE_DIR
|
||||
|
||||
echo "Setting up genesis..."
|
||||
SERVE_DIR=${BASE_DIR}/server
|
||||
SERVER_LOG=${BASE_DIR}/${SERVER_EXE}.log
|
||||
|
||||
echo "Starting ${SERVER_EXE} server..."
|
||||
export EYE_HOME=${SERVE_DIR}
|
||||
${SERVER_EXE} init --chain-id=$CHAIN_ID >>$SERVER_LOG
|
||||
startServer $SERVE_DIR $SERVER_LOG
|
||||
[ $? = 0 ] || return 1
|
||||
|
||||
# Set up client - make sure you use the proper prefix if you set
|
||||
# a custom CLIENT_EXE
|
||||
export EYE_HOME=${BASE_DIR}/client
|
||||
|
||||
initClient $CHAIN_ID
|
||||
[ $? = 0 ] || return 1
|
||||
|
||||
printf "...Testing may begin!\n\n\n"
|
||||
}
|
||||
|
||||
oneTimeTearDown() {
|
||||
quickTearDown
|
||||
}
|
||||
|
||||
test00SetGetRemove() {
|
||||
KEY="CAFE6000"
|
||||
VALUE="F00D4200"
|
||||
|
||||
assertFalse "line=${LINENO} data present" "${CLIENT_EXE} query eyes ${KEY}"
|
||||
|
||||
# set data
|
||||
TXRES=$(${CLIENT_EXE} tx set --key=${KEY} --value=${VALUE})
|
||||
txSucceeded $? "$TXRES" "set cafe"
|
||||
HASH=$(echo $TXRES | jq .hash | tr -d \")
|
||||
TX_HEIGHT=$(echo $TXRES | jq .height)
|
||||
|
||||
# make sure it is set
|
||||
DATA=$(${CLIENT_EXE} query eyes ${KEY} --height=$TX_HEIGHT)
|
||||
assertTrue "line=${LINENO} data not set" $?
|
||||
assertEquals "line=${LINENO}" "\"${VALUE}\"" $(echo $DATA | jq .data.value)
|
||||
|
||||
# query the tx
|
||||
TX=$(${CLIENT_EXE} query tx $HASH)
|
||||
assertTrue "line=${LINENO}, found tx" $?
|
||||
if [ -n "$DEBUG" ]; then echo $TX; echo; fi
|
||||
|
||||
assertEquals "line=${LINENO}, proper type" "\"eyes/set\"" $(echo $TX | jq .data.type)
|
||||
assertEquals "line=${LINENO}, proper key" "\"${KEY}\"" $(echo $TX | jq .data.data.key)
|
||||
assertEquals "line=${LINENO}, proper value" "\"${VALUE}\"" $(echo $TX | jq .data.data.value)
|
||||
}
|
||||
|
||||
|
||||
# Load common then run these tests with shunit2!
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
|
||||
CLI_DIR=$GOPATH/src/github.com/cosmos/cosmos-sdk/tests/cli
|
||||
|
||||
. $CLI_DIR/common.sh
|
||||
. $CLI_DIR/shunit2
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package eyes
|
||||
|
||||
import (
|
||||
wire "github.com/tendermint/go-wire"
|
||||
|
||||
eyesmod "github.com/cosmos/cosmos-sdk/modules/eyes"
|
||||
"github.com/cosmos/cosmos-sdk/util"
|
||||
)
|
||||
|
||||
// Tx is what is submitted to the chain.
|
||||
// This embeds the tx data along with any info we want for
|
||||
// decorators (just chain for now to demo)
|
||||
type Tx struct {
|
||||
Tx eyesmod.EyesTx `json:"tx"`
|
||||
Chain util.ChainData `json:"chain"`
|
||||
}
|
||||
|
||||
// GetTx gets the tx info
|
||||
func (e Tx) GetTx() interface{} {
|
||||
return e.Tx
|
||||
}
|
||||
|
||||
// GetChain gets the chain we wish to perform the tx on
|
||||
// (info for decorators)
|
||||
func (e Tx) GetChain() util.ChainData {
|
||||
return e.Chain
|
||||
}
|
||||
|
||||
// LoadTx parses the input data into our blockchain tx structure
|
||||
func LoadTx(data []byte) (tx Tx, err error) {
|
||||
err = wire.ReadBinaryBytes(data, &tx)
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user