Merge branch 'testnet-fixes' into develop
This commit is contained in:
commit
b566b85fd6
12
app/app.go
12
app/app.go
|
@ -1,6 +1,7 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
|
@ -77,13 +78,18 @@ func (app *Basecoin) SetOption(key string, value string) string {
|
|||
app.state.SetChainID(value)
|
||||
return "Success"
|
||||
case "account":
|
||||
var acc types.Account
|
||||
var acc GenesisAccount
|
||||
err := json.Unmarshal([]byte(value), &acc)
|
||||
if err != nil {
|
||||
return "Error decoding acc message: " + err.Error()
|
||||
}
|
||||
app.state.SetAccount(acc.PubKey.Address(), &acc)
|
||||
app.logger.Info("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
|
||||
acc.Balance.Sort()
|
||||
addr, err := acc.GetAddr()
|
||||
if err != nil {
|
||||
return "Invalid address: " + err.Error()
|
||||
}
|
||||
app.state.SetAccount(addr, acc.ToAccount())
|
||||
app.logger.Info("SetAccount", "addr", hex.EncodeToString(addr), "acc", acc)
|
||||
|
||||
return "Success"
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
eyes "github.com/tendermint/merkleeyes/client"
|
||||
|
@ -103,6 +104,7 @@ func TestSplitKey(t *testing.T) {
|
|||
|
||||
func TestSetOption(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
eyesCli := eyes.NewLocalClient("", 0)
|
||||
app := NewBasecoin(eyesCli)
|
||||
|
@ -114,11 +116,43 @@ func TestSetOption(t *testing.T) {
|
|||
assert.EqualValues(app.GetState().GetChainID(), chainID)
|
||||
assert.EqualValues(res, "Success")
|
||||
|
||||
// make a nice account...
|
||||
accIn := types.MakeAcc("input0")
|
||||
accsInBytes, err := json.Marshal(accIn.Account)
|
||||
assert.Nil(err)
|
||||
res = app.SetOption("base/account", string(accsInBytes))
|
||||
assert.EqualValues(res, "Success")
|
||||
require.EqualValues(res, "Success")
|
||||
// make sure it is set correctly, with some balance
|
||||
acct := state.GetAccount(app.GetState(), accIn.PubKey.Address())
|
||||
require.NotNil(acct)
|
||||
assert.Equal(accIn.Balance, acct.Balance)
|
||||
|
||||
// let's parse an account with badly sorted coins...
|
||||
unsortAddr, err := hex.DecodeString("C471FB670E44D219EE6DF2FC284BE38793ACBCE1")
|
||||
require.Nil(err)
|
||||
unsortCoins := types.Coins{{"BTC", 789}, {"eth", 123}}
|
||||
unsortAcc := `{
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "AD084F0572C116D618B36F2EB08240D1BAB4B51716CCE0E7734B89C8936DCE9A"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "eth",
|
||||
"amount": 123
|
||||
},
|
||||
{
|
||||
"denom": "BTC",
|
||||
"amount": 789
|
||||
}
|
||||
]
|
||||
}`
|
||||
res = app.SetOption("base/account", unsortAcc)
|
||||
require.EqualValues(res, "Success")
|
||||
acct = state.GetAccount(app.GetState(), unsortAddr)
|
||||
require.NotNil(acct)
|
||||
assert.True(acct.Balance.IsValid())
|
||||
assert.Equal(unsortCoins, acct.Balance)
|
||||
|
||||
res = app.SetOption("base/dslfkgjdas", "")
|
||||
assert.NotEqual(res, "Success")
|
||||
|
@ -128,6 +162,7 @@ func TestSetOption(t *testing.T) {
|
|||
|
||||
res = app.SetOption("dslfkgjdas/szfdjzs", "")
|
||||
assert.NotEqual(res, "Success")
|
||||
|
||||
}
|
||||
|
||||
// Test CheckTx and DeliverTx with insufficient and sufficient balance
|
||||
|
@ -179,7 +214,5 @@ func TestQuery(t *testing.T) {
|
|||
Path: "/account",
|
||||
Data: at.accIn.Account.PubKey.Address(),
|
||||
})
|
||||
fmt.Println(resQueryPreCommit)
|
||||
fmt.Println(resQueryPostCommit)
|
||||
assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit")
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/basecoin/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
@ -49,7 +52,7 @@ type FullGenesisDoc struct {
|
|||
}
|
||||
|
||||
type GenesisDoc struct {
|
||||
Accounts []types.Account `json:"accounts"`
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
PluginOptions []json.RawMessage `json:"plugin_options"`
|
||||
|
||||
pluginOptions []keyValue // unmarshaled rawmessages
|
||||
|
@ -98,3 +101,40 @@ func parseGenesisList(kvz_ []json.RawMessage) (kvz []keyValue, err error) {
|
|||
}
|
||||
return kvz, nil
|
||||
}
|
||||
|
||||
/**** code to parse accounts from genesis docs ***/
|
||||
|
||||
type GenesisAccount struct {
|
||||
Address data.Bytes `json:"address"`
|
||||
// this from types.Account (don't know how to embed this properly)
|
||||
PubKey crypto.PubKey `json:"pub_key"` // May be nil, if not known.
|
||||
Sequence int `json:"sequence"`
|
||||
Balance types.Coins `json:"coins"`
|
||||
}
|
||||
|
||||
func (g GenesisAccount) ToAccount() *types.Account {
|
||||
return &types.Account{
|
||||
PubKey: g.PubKey,
|
||||
Sequence: g.Sequence,
|
||||
Balance: g.Balance,
|
||||
}
|
||||
}
|
||||
|
||||
func (g GenesisAccount) GetAddr() ([]byte, error) {
|
||||
noAddr, noPk := len(g.Address) == 0, g.PubKey.Empty()
|
||||
|
||||
if noAddr {
|
||||
if noPk {
|
||||
return nil, errors.New("No address given")
|
||||
}
|
||||
return g.PubKey.Address(), nil
|
||||
}
|
||||
if noPk { // but is addr...
|
||||
return g.Address, nil
|
||||
}
|
||||
// now, we have both, make sure they check out
|
||||
if bytes.Equal(g.Address, g.PubKey.Address()) {
|
||||
return g.Address, nil
|
||||
}
|
||||
return nil, errors.New("Address and pubkey don't match")
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
"github.com/tendermint/go-crypto"
|
||||
eyescli "github.com/tendermint/merkleeyes/client"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
const genesisFilepath = "./testdata/genesis.json"
|
||||
const genesisAcctFilepath = "./testdata/genesis2.json"
|
||||
|
||||
func TestLoadGenesis(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
@ -34,8 +36,12 @@ func TestLoadGenesis(t *testing.T) {
|
|||
|
||||
// make sure balance is proper
|
||||
assert.Equal(2, len(acct.Balance))
|
||||
assert.EqualValues(12345, acct.Balance[0].Amount)
|
||||
assert.EqualValues("blank", acct.Balance[0].Denom)
|
||||
assert.True(acct.Balance.IsValid())
|
||||
// note, that we now sort them to be valid
|
||||
assert.EqualValues(654321, acct.Balance[0].Amount)
|
||||
assert.EqualValues("ETH", acct.Balance[0].Denom)
|
||||
assert.EqualValues(12345, acct.Balance[1].Amount)
|
||||
assert.EqualValues("blank", acct.Balance[1].Denom)
|
||||
|
||||
// and public key is parsed properly
|
||||
apk := acct.PubKey.Unwrap()
|
||||
|
@ -46,6 +52,51 @@ func TestLoadGenesis(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Fix for issue #89, change the parse format for accounts in genesis.json
|
||||
func TestLoadGenesisAccountAddress(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
eyesCli := eyescli.NewLocalClient("", 0)
|
||||
app := NewBasecoin(eyesCli)
|
||||
err := app.LoadGenesis(genesisAcctFilepath)
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
// check the chain id
|
||||
assert.Equal("addr_accounts_chain", app.GetState().GetChainID())
|
||||
|
||||
// make sure the accounts were set properly
|
||||
cases := []struct {
|
||||
addr string
|
||||
exists bool
|
||||
hasPubkey bool
|
||||
coins types.Coins
|
||||
}{
|
||||
// this comes from a public key, should be stored proper (alice)
|
||||
{"62035D628DE7543332544AA60D90D3693B6AD51B", true, true, types.Coins{{"one", 111}}},
|
||||
// this comes from an address, should be stored proper (bob)
|
||||
{"C471FB670E44D219EE6DF2FC284BE38793ACBCE1", true, false, types.Coins{{"two", 222}}},
|
||||
// this one had a mismatched address and pubkey, should not store under either (carl)
|
||||
{"1234ABCDD18E8EFE3FFC4B0506BF9BF8E5B0D9E9", false, false, nil}, // this is given addr
|
||||
{"700BEC5ED18E8EFE3FFC4B0506BF9BF8E5B0D9E9", false, false, nil}, // this is addr of the given pubkey
|
||||
// this comes from a secp256k1 public key, should be stored proper (sam)
|
||||
{"979F080B1DD046C452C2A8A250D18646C6B669D4", true, true, types.Coins{{"four", 444}}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
addr, err := hex.DecodeString(tc.addr)
|
||||
require.Nil(err, tc.addr)
|
||||
acct := app.GetState().GetAccount(addr)
|
||||
if !tc.exists {
|
||||
assert.Nil(acct, tc.addr)
|
||||
} else if assert.NotNil(acct, tc.addr) {
|
||||
// it should and does exist...
|
||||
assert.True(acct.Balance.IsValid())
|
||||
assert.Equal(tc.coins, acct.Balance)
|
||||
assert.Equal(!tc.hasPubkey, acct.PubKey.Empty(), tc.addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseGenesisList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"chain_id": "addr_accounts_chain",
|
||||
"app_options": {
|
||||
"accounts": [{
|
||||
"name": "alice",
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "DBD9A46C45868F0A37C92B53113C09B048FBD87B5FBC2F8B199052973B8FAA36"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "one",
|
||||
"amount": 111
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"name": "bob",
|
||||
"address": "C471FB670E44D219EE6DF2FC284BE38793ACBCE1",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "two",
|
||||
"amount": 222
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"name": "carl",
|
||||
"address": "1234ABCDD18E8EFE3FFC4B0506BF9BF8E5B0D9E9",
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "177C0AC45E86257F0708DC085D592AB22AAEECD1D26381B757F7C96135921858"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "three",
|
||||
"amount": 333
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"name": "sam",
|
||||
"pub_key": {
|
||||
"type": "secp256k1",
|
||||
"data": "02AA8342F63CCCCE6DDB128525BA048CE0B2993DA3B4308746E1F216361A87651E"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "four",
|
||||
"amount": 444
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
|
@ -107,9 +107,15 @@ func (t SendTxReader) ReadTxFlags(flags interface{}, pk crypto.PubKey) (interfac
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// get addr if available
|
||||
var addr []byte
|
||||
if !pk.Empty() {
|
||||
addr = pk.Address()
|
||||
}
|
||||
|
||||
// craft the tx
|
||||
input := btypes.TxInput{
|
||||
Address: pk.Address(),
|
||||
Address: addr,
|
||||
Coins: amountCoins,
|
||||
Sequence: data.Sequence,
|
||||
}
|
||||
|
@ -174,9 +180,15 @@ func (t AppTxReader) ReadTxFlags(data *AppFlags, app string, appData []byte, pk
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// get addr if available
|
||||
var addr []byte
|
||||
if !pk.Empty() {
|
||||
addr = pk.Address()
|
||||
}
|
||||
|
||||
// craft the tx
|
||||
input := btypes.TxInput{
|
||||
Address: pk.Address(),
|
||||
Address: addr,
|
||||
Coins: amountCoins,
|
||||
Sequence: data.Sequence,
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
)
|
||||
|
||||
var UnsafeResetAllCmd = &cobra.Command{
|
||||
|
@ -17,9 +13,10 @@ var UnsafeResetAllCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
func unsafeResetAllCmd(cmd *cobra.Command, args []string) error {
|
||||
rootDir := viper.GetString(cli.HomeFlag)
|
||||
// wipe out rootdir if it exists before recreating it
|
||||
os.RemoveAll(rootDir)
|
||||
config.EnsureRoot(rootDir)
|
||||
cfg, err := getTendermintConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmcmd.ResetAll(cfg.DBDir(), cfg.PrivValidatorFile(), logger)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -122,14 +122,22 @@ func startBasecoinABCI(basecoinApp *app.Basecoin) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||
func getTendermintConfig() (*config.Config, error) {
|
||||
cfg := config.DefaultConfig()
|
||||
err := viper.Unmarshal(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
cfg.SetRoot(cfg.RootDir)
|
||||
config.EnsureRoot(cfg.RootDir)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||
cfg, err := getTendermintConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: parse the log level from the config properly (multi modules)
|
||||
// but some tm code must be refactored for better usability
|
||||
|
|
|
@ -3,8 +3,11 @@ package types
|
|||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Coin struct {
|
||||
|
@ -53,9 +56,8 @@ func (coins Coins) String() string {
|
|||
}
|
||||
|
||||
func ParseCoins(str string) (Coins, error) {
|
||||
|
||||
split := strings.Split(str, ",")
|
||||
var coins []Coin
|
||||
var coins Coins
|
||||
|
||||
for _, el := range split {
|
||||
if len(el) > 0 {
|
||||
|
@ -67,6 +69,12 @@ func ParseCoins(str string) (Coins, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// ensure they are in proper order, to avoid random failures later
|
||||
coins.Sort()
|
||||
if !coins.IsValid() {
|
||||
return nil, errors.Errorf("ParseCoins invalid: %#v", coins)
|
||||
}
|
||||
|
||||
return coins, nil
|
||||
}
|
||||
|
||||
|
@ -195,3 +203,10 @@ func (coins Coins) IsNonnegative() bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/*** Implement Sort interface ***/
|
||||
|
||||
func (c Coins) Len() int { return len(c) }
|
||||
func (c Coins) Less(i, j int) bool { return c[i].Denom < c[j].Denom }
|
||||
func (c Coins) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
func (c Coins) Sort() { sort.Sort(c) }
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCoins(t *testing.T) {
|
||||
|
@ -56,30 +55,79 @@ func TestCoins(t *testing.T) {
|
|||
|
||||
//Test the parse coin and parse coins functionality
|
||||
func TestParse(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
assert := assert.New(t)
|
||||
|
||||
makeCoin := func(str string) Coin {
|
||||
coin, err := ParseCoin(str)
|
||||
require.Nil(err)
|
||||
return coin
|
||||
cases := []struct {
|
||||
input string
|
||||
valid bool // if false, we expect an error on parse
|
||||
expected Coins // if valid is true, make sure this is returned
|
||||
}{
|
||||
{"", true, nil},
|
||||
{"1foo", true, Coins{{"foo", 1}}},
|
||||
{"10bar", true, Coins{{"bar", 10}}},
|
||||
{"99bar,1foo", true, Coins{{"bar", 99}, {"foo", 1}}},
|
||||
{"98 bar , 1 foo ", true, Coins{{"bar", 98}, {"foo", 1}}},
|
||||
{"2foo, 97 bar", true, Coins{{"bar", 97}, {"foo", 2}}},
|
||||
}
|
||||
|
||||
makeCoins := func(str string) Coins {
|
||||
coin, err := ParseCoins(str)
|
||||
require.Nil(err)
|
||||
return coin
|
||||
for _, tc := range cases {
|
||||
res, err := ParseCoins(tc.input)
|
||||
if !tc.valid {
|
||||
assert.NotNil(err, tc.input)
|
||||
} else if assert.Nil(err, "%s: %+v", tc.input, err) {
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
//testing ParseCoin Function
|
||||
assert.Equal(Coin{}, makeCoin(""), "ParseCoin makes bad empty coin")
|
||||
assert.Equal(Coin{"fooCoin", 1}, makeCoin("1fooCoin"), "ParseCoin makes bad coins")
|
||||
assert.Equal(Coin{"barCoin", 10}, makeCoin("10 barCoin"), "ParseCoin makes bad coins")
|
||||
|
||||
//testing ParseCoins Function
|
||||
assert.True(Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")),
|
||||
"ParseCoins doesn't parse a single coin")
|
||||
assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")),
|
||||
"ParseCoins doesn't properly parse two coins")
|
||||
assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")),
|
||||
"ParseCoins doesn't properly parse two coins which use spaces")
|
||||
}
|
||||
|
||||
func TestSortCoins(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
good := Coins{
|
||||
Coin{"GAS", 1},
|
||||
Coin{"MINERAL", 1},
|
||||
Coin{"TREE", 1},
|
||||
}
|
||||
empty := Coins{
|
||||
Coin{"GOLD", 0},
|
||||
}
|
||||
badSort1 := Coins{
|
||||
Coin{"TREE", 1},
|
||||
Coin{"GAS", 1},
|
||||
Coin{"MINERAL", 1},
|
||||
}
|
||||
badSort2 := Coins{ // both are after the first one, but the second and third are in the wrong order
|
||||
Coin{"GAS", 1},
|
||||
Coin{"TREE", 1},
|
||||
Coin{"MINERAL", 1},
|
||||
}
|
||||
badAmt := Coins{
|
||||
Coin{"GAS", 1},
|
||||
Coin{"TREE", 0},
|
||||
Coin{"MINERAL", 1},
|
||||
}
|
||||
dup := Coins{
|
||||
Coin{"GAS", 1},
|
||||
Coin{"GAS", 1},
|
||||
Coin{"MINERAL", 1},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
coins Coins
|
||||
before, after bool // valid before/after sort
|
||||
}{
|
||||
{good, true, true},
|
||||
{empty, false, false},
|
||||
{badSort1, false, true},
|
||||
{badSort2, false, true},
|
||||
{badAmt, false, false},
|
||||
{dup, false, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
assert.Equal(tc.before, tc.coins.IsValid())
|
||||
tc.coins.Sort()
|
||||
assert.Equal(tc.after, tc.coins.IsValid())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue