Removed a whole lot of old crud

This commit is contained in:
Ethan Frey 2017-07-06 13:40:02 +02:00
parent 5c813833a0
commit 912c24093f
15 changed files with 311 additions and 1008 deletions

View File

@ -2,7 +2,6 @@ package app
import (
"encoding/hex"
"encoding/json"
"os"
"testing"
@ -15,7 +14,6 @@ import (
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/txs"
"github.com/tendermint/basecoin/types"
crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
eyes "github.com/tendermint/merkleeyes/client"
"github.com/tendermint/tmlibs/log"
@ -28,8 +26,8 @@ type appTest struct {
t *testing.T
chainID string
app *Basecoin
accIn types.PrivAccount
accOut types.PrivAccount
acctIn *coin.AccountWithKey
acctOut *coin.AccountWithKey
}
func newAppTest(t *testing.T) *appTest {
@ -41,32 +39,27 @@ func newAppTest(t *testing.T) *appTest {
return at
}
// make a tx sending 5mycoin from each accIn to accOut
// make a tx sending 5mycoin from each acctIn to acctOut
func (at *appTest) getTx(seq int, coins types.Coins) basecoin.Tx {
addrIn := at.accIn.Account.PubKey.Address()
addrOut := at.accOut.Account.PubKey.Address()
in := []coin.TxInput{{Address: stack.SigPerm(addrIn), Coins: coins, Sequence: seq}}
out := []coin.TxOutput{{Address: stack.SigPerm(addrOut), Coins: coins}}
in := []coin.TxInput{{Address: at.acctIn.Actor(), Coins: coins, Sequence: seq}}
out := []coin.TxOutput{{Address: at.acctOut.Actor(), Coins: coins}}
tx := coin.NewSendTx(in, out)
tx = txs.NewChain(at.chainID, tx)
stx := txs.NewMulti(tx)
txs.Sign(stx, at.accIn.PrivKey)
txs.Sign(stx, at.acctIn.Key)
return stx.Wrap()
}
// set the account on the app through SetOption
func (at *appTest) acc2app(acc types.Account) {
accBytes, err := json.Marshal(acc)
require.Nil(at.t, err)
res := at.app.SetOption("coin/account", string(accBytes))
func (at *appTest) initAccount(acct *coin.AccountWithKey) {
res := at.app.SetOption("coin/account", acct.MakeOption())
require.EqualValues(at.t, res, "Success")
}
// reset the in and out accs to be one account each with 7mycoin
func (at *appTest) reset() {
at.accIn = types.MakeAcc("input0")
at.accOut = types.MakeAcc("output0")
at.acctIn = coin.NewAccountWithKey(types.Coins{{"mycoin", 7}})
at.acctOut = coin.NewAccountWithKey(types.Coins{{"mycoin", 7}})
eyesCli := eyes.NewLocalClient("", 0)
// logger := log.TestingLogger().With("module", "app"),
@ -81,30 +74,30 @@ func (at *appTest) reset() {
res := at.app.SetOption("base/chain_id", at.chainID)
require.EqualValues(at.t, res, "Success")
at.acc2app(at.accIn.Account)
at.acc2app(at.accOut.Account)
at.initAccount(at.acctIn)
at.initAccount(at.acctOut)
resabci := at.app.Commit()
require.True(at.t, resabci.IsOK(), resabci)
}
func getBalance(pk crypto.PubKey, state types.KVStore) (types.Coins, error) {
return getAddr(pk.Address(), state)
func getBalance(key basecoin.Actor, state types.KVStore) (types.Coins, error) {
acct, err := coin.NewAccountant("").GetAccount(state, key)
return acct.Coins, err
}
func getAddr(addr []byte, state types.KVStore) (types.Coins, error) {
actor := stack.SigPerm(addr)
acct, err := coin.NewAccountant("").GetAccount(state, actor)
return acct.Coins, err
return getBalance(actor, state)
}
// returns the final balance and expected balance for input and output accounts
func (at *appTest) exec(t *testing.T, tx basecoin.Tx, checkTx bool) (res abci.Result, diffIn, diffOut types.Coins) {
require := require.New(t)
initBalIn, err := getBalance(at.accIn.Account.PubKey, at.app.GetState())
initBalIn, err := getBalance(at.acctIn.Actor(), at.app.GetState())
require.Nil(err, "%+v", err)
initBalOut, err := getBalance(at.accOut.Account.PubKey, at.app.GetState())
initBalOut, err := getBalance(at.acctOut.Actor(), at.app.GetState())
require.Nil(err, "%+v", err)
txBytes := wire.BinaryBytes(tx)
@ -114,9 +107,9 @@ func (at *appTest) exec(t *testing.T, tx basecoin.Tx, checkTx bool) (res abci.Re
res = at.app.DeliverTx(txBytes)
}
endBalIn, err := getBalance(at.accIn.Account.PubKey, at.app.GetState())
endBalIn, err := getBalance(at.acctIn.Actor(), at.app.GetState())
require.Nil(err, "%+v", err)
endBalOut, err := getBalance(at.accOut.Account.PubKey, at.app.GetState())
endBalOut, err := getBalance(at.acctOut.Actor(), at.app.GetState())
require.Nil(err, "%+v", err)
return res, endBalIn.Minus(initBalIn), endBalOut.Minus(initBalOut)
}
@ -141,16 +134,15 @@ func TestSetOption(t *testing.T) {
assert.EqualValues(res, "Success")
// make a nice account...
accIn := types.MakeAcc("input0").Account
accsInBytes, err := json.Marshal(accIn)
assert.Nil(err)
res = app.SetOption("coin/account", string(accsInBytes))
bal := types.Coins{{"atom", 77}, {"eth", 12}}
acct := coin.NewAccountWithKey(bal)
res = app.SetOption("coin/account", acct.MakeOption())
require.EqualValues(res, "Success")
// make sure it is set correctly, with some balance
coins, err := getBalance(accIn.PubKey, app.state)
coins, err := getBalance(acct.Actor(), app.state)
require.Nil(err)
assert.Equal(accIn.Balance, coins)
assert.Equal(bal, coins)
// let's parse an account with badly sorted coins...
unsortAddr, err := hex.DecodeString("C471FB670E44D219EE6DF2FC284BE38793ACBCE1")
@ -197,8 +189,8 @@ func TestTx(t *testing.T) {
at := newAppTest(t)
//Bad Balance
at.accIn.Balance = types.Coins{{"mycoin", 2}}
at.acc2app(at.accIn.Account)
at.acctIn.Coins = types.Coins{{"mycoin", 2}}
at.initAccount(at.acctIn)
res, _, _ := at.exec(t, at.getTx(1, types.Coins{{"mycoin", 5}}), true)
assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)
res, diffIn, diffOut := at.exec(t, at.getTx(1, types.Coins{{"mycoin", 5}}), false)
@ -229,7 +221,7 @@ func TestQuery(t *testing.T) {
resQueryPreCommit := at.app.Query(abci.RequestQuery{
Path: "/account",
Data: at.accIn.Account.PubKey.Address(),
Data: at.acctIn.Address(),
})
res = at.app.Commit()
@ -237,7 +229,7 @@ func TestQuery(t *testing.T) {
resQueryPostCommit := at.app.Query(abci.RequestQuery{
Path: "/account",
Data: at.accIn.Account.PubKey.Address(),
Data: at.acctIn.Address(),
})
assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit")
}

View File

@ -1,31 +0,0 @@
package commands
import (
"fmt"
"github.com/spf13/cobra"
"github.com/tendermint/basecoin/types"
)
type plugin struct {
name string
newPlugin func() types.Plugin
}
var plugins = []plugin{}
// RegisterStartPlugin - used to enable a plugin
func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
plugins = append(plugins, plugin{name: name, newPlugin: newPlugin})
}
// QuickVersionCmd - returns a version command based on version input
func QuickVersionCmd(version string) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Show version info",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(version)
},
}
}

View File

@ -1,19 +1,6 @@
package commands
import (
"encoding/hex"
"fmt"
"github.com/pkg/errors"
abci "github.com/tendermint/abci/types"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/basecoin/types"
client "github.com/tendermint/tendermint/rpc/client"
tmtypes "github.com/tendermint/tendermint/types"
)
import "encoding/hex"
// Returns true for non-empty hex-string prefixed with "0x"
func isHex(s string) bool {
@ -34,77 +21,3 @@ func StripHex(s string) string {
}
return s
}
// Query - send an abci query
func Query(tmAddr string, key []byte) (*abci.ResultQuery, error) {
httpClient := client.NewHTTP(tmAddr, "/websocket")
return queryWithClient(httpClient, key)
}
func queryWithClient(httpClient *client.HTTP, key []byte) (*abci.ResultQuery, error) {
res, err := httpClient.ABCIQuery("/key", key, true)
if err != nil {
return nil, errors.Errorf("Error calling /abci_query: %v", err)
}
if !res.Code.IsOK() {
return nil, errors.Errorf("Query got non-zero exit code: %v. %s", res.Code, res.Log)
}
return res.ResultQuery, nil
}
// fetch the account by querying the app
func getAccWithClient(httpClient *client.HTTP, address []byte) (*types.Account, error) {
key := types.AccountKey(address)
response, err := queryWithClient(httpClient, key)
if err != nil {
return nil, err
}
accountBytes := response.Value
if len(accountBytes) == 0 {
return nil, fmt.Errorf("Account bytes are empty for address: %X ", address) //never stack trace
}
var acc *types.Account
err = wire.ReadBinaryBytes(accountBytes, &acc)
if err != nil {
return nil, errors.Errorf("Error reading account %X error: %v",
accountBytes, err.Error())
}
return acc, nil
}
func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Commit, error) {
httpClient := client.NewHTTP(tmAddr, "/websocket")
res, err := httpClient.Commit(height)
if err != nil {
return nil, nil, errors.Errorf("Error on commit: %v", err)
}
header := res.Header
commit := res.Commit
return header, commit, nil
}
func waitForBlock(httpClient *client.HTTP) error {
res, err := httpClient.Status()
if err != nil {
return err
}
lastHeight := res.LatestBlockHeight
for {
res, err := httpClient.Status()
if err != nil {
return err
}
if res.LatestBlockHeight > lastHeight {
break
}
}
return nil
}

View File

@ -16,3 +16,14 @@ var VersionCmd = &cobra.Command{
fmt.Println(version.Version)
},
}
// QuickVersionCmd - returns a version command based on version input
func QuickVersionCmd(version string) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Show version info",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(version)
},
}
}

View File

@ -1,7 +1,6 @@
package counter
import (
"encoding/json"
"os"
"testing"
@ -9,6 +8,7 @@ import (
"github.com/stretchr/testify/require"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/app"
"github.com/tendermint/basecoin/modules/coin"
"github.com/tendermint/basecoin/txs"
"github.com/tendermint/basecoin/types"
"github.com/tendermint/go-wire"
@ -34,14 +34,9 @@ func TestCounterPlugin(t *testing.T) {
bcApp.SetOption("base/chain_id", chainID)
// Account initialization
test1PrivAcc := types.PrivAccountFromSecret("test1")
// Seed Basecoin with account
test1Acc := test1PrivAcc.Account
test1Acc.Balance = types.Coins{{"", 1000}, {"gold", 1000}}
accOpt, err := json.Marshal(test1Acc)
require.Nil(t, err)
log := bcApp.SetOption("coin/account", string(accOpt))
bal := types.Coins{{"", 1000}, {"gold", 1000}}
acct := coin.NewAccountWithKey(bal)
log := bcApp.SetOption("coin/account", acct.MakeOption())
require.Equal(t, "Success", log)
// Deliver a CounterTx
@ -49,7 +44,7 @@ func TestCounterPlugin(t *testing.T) {
tx := NewTx(valid, counterFee, inputSequence)
tx = txs.NewChain(chainID, tx)
stx := txs.NewSig(tx)
txs.Sign(stx, test1PrivAcc.PrivKey)
txs.Sign(stx, acct.Key)
txBytes := wire.BinaryBytes(stx.Wrap())
return bcApp.DeliverTx(txBytes)
}

51
modules/coin/helper.go Normal file
View File

@ -0,0 +1,51 @@
package coin
import (
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/types"
crypto "github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire/data"
)
// AccountWithKey is a helper for tests, that includes and account
// along with the private key to access it.
type AccountWithKey struct {
Key crypto.PrivKey
Account
}
// NewAccountWithKey creates an account with the given balance
// and a random private key
func NewAccountWithKey(coins types.Coins) *AccountWithKey {
return &AccountWithKey{
Key: crypto.GenPrivKeyEd25519().Wrap(),
Account: Account{Coins: coins},
}
}
// Address returns the public key address for this account
func (a *AccountWithKey) Address() []byte {
return a.Key.PubKey().Address()
}
// Actor returns the basecoin actor associated with this account
func (a *AccountWithKey) Actor() basecoin.Actor {
return stack.SigPerm(a.Key.PubKey().Address())
}
// MakeOption returns a string to use with SetOption to initialize this account
//
// This is intended for use in test cases
func (a *AccountWithKey) MakeOption() string {
info := GenesisAccount{
Address: a.Address(),
Sequence: a.Sequence,
Balance: a.Coins,
}
js, err := data.ToJSON(info)
if err != nil {
panic(err)
}
return string(js)
}

View File

@ -20,9 +20,6 @@ func TestState(t *testing.T) {
cache := state.CacheWrap()
eyesCli := eyes.NewLocalClient("", 0)
acc := new(types.Account)
acc.Sequence = 1
//reset the store/state/cache
reset := func() {
store = types.NewMemKVStore()

View File

@ -1,140 +1,142 @@
package main
import (
"fmt"
"time"
func main() {}
"github.com/gorilla/websocket"
"github.com/tendermint/basecoin/types"
wire "github.com/tendermint/go-wire"
_ "github.com/tendermint/tendermint/rpc/core/types" // Register RPCResponse > Result types
"github.com/tendermint/tendermint/rpc/lib/client"
"github.com/tendermint/tendermint/rpc/lib/types"
cmn "github.com/tendermint/tmlibs/common"
)
// import (
// "fmt"
// "time"
func main() {
// ws := rpcclient.NewWSClient("127.0.0.1:46657", "/websocket")
ws := rpcclient.NewWSClient("192.168.99.100:46657", "/websocket")
chainID := "test_chain_id"
// "github.com/gorilla/websocket"
// "github.com/tendermint/basecoin/types"
// wire "github.com/tendermint/go-wire"
// _ "github.com/tendermint/tendermint/rpc/core/types" // Register RPCResponse > Result types
// "github.com/tendermint/tendermint/rpc/lib/client"
// "github.com/tendermint/tendermint/rpc/lib/types"
// cmn "github.com/tendermint/tmlibs/common"
// )
_, err := ws.Start()
if err != nil {
cmn.Exit(err.Error())
}
var counter = 0
// func main() {
// // ws := rpcclient.NewWSClient("127.0.0.1:46657", "/websocket")
// ws := rpcclient.NewWSClient("192.168.99.100:46657", "/websocket")
// chainID := "test_chain_id"
// Read a bunch of responses
go func() {
for {
res, ok := <-ws.ResultsCh
if !ok {
break
}
fmt.Println(counter, "res:", cmn.Blue(string(res)))
}
}()
// _, err := ws.Start()
// if err != nil {
// cmn.Exit(err.Error())
// }
// var counter = 0
// Get the root account
root := types.PrivAccountFromSecret("test")
sequence := int(0)
// Make a bunch of PrivAccounts
privAccounts := types.RandAccounts(1000, 1000000, 0)
privAccountSequences := make(map[string]int)
// // Read a bunch of responses
// go func() {
// for {
// res, ok := <-ws.ResultsCh
// if !ok {
// break
// }
// fmt.Println(counter, "res:", cmn.Blue(string(res)))
// }
// }()
// Send coins to each account
for i := 0; i < len(privAccounts); i++ {
privAccount := privAccounts[i]
tx := &types.SendTx{
Inputs: []types.TxInput{
types.TxInput{
Address: root.Account.PubKey.Address(),
PubKey: root.Account.PubKey, // TODO is this needed?
Coins: types.Coins{{"", 1000002}},
Sequence: sequence,
},
},
Outputs: []types.TxOutput{
types.TxOutput{
Address: privAccount.Account.PubKey.Address(),
Coins: types.Coins{{"", 1000000}},
},
},
}
sequence += 1
// // Get the root account
// root := types.PrivAccountFromSecret("test")
// sequence := int(0)
// // Make a bunch of PrivAccounts
// privAccounts := types.RandAccounts(1000, 1000000, 0)
// privAccountSequences := make(map[string]int)
// Sign request
signBytes := tx.SignBytes(chainID)
sig := root.Sign(signBytes)
tx.Inputs[0].Signature = sig
//fmt.Println("tx:", tx)
// // Send coins to each account
// for i := 0; i < len(privAccounts); i++ {
// privAccount := privAccounts[i]
// tx := &types.SendTx{
// Inputs: []types.TxInput{
// types.TxInput{
// Address: root.Account.PubKey.Address(),
// PubKey: root.Account.PubKey, // TODO is this needed?
// Coins: types.Coins{{"", 1000002}},
// Sequence: sequence,
// },
// },
// Outputs: []types.TxOutput{
// types.TxOutput{
// Address: privAccount.Account.PubKey.Address(),
// Coins: types.Coins{{"", 1000000}},
// },
// },
// }
// sequence += 1
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
request, err := rpctypes.MapToRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes})
if err != nil {
cmn.Exit("cannot encode request: " + err.Error())
}
reqBytes := wire.JSONBytes(request)
//fmt.Print(".")
err = ws.WriteMessage(websocket.TextMessage, reqBytes)
if err != nil {
cmn.Exit("writing websocket request: " + err.Error())
}
}
// // Sign request
// signBytes := tx.SignBytes(chainID)
// sig := root.Sign(signBytes)
// tx.Inputs[0].Signature = sig
// //fmt.Println("tx:", tx)
// Now send coins between these accounts
for {
counter += 1
time.Sleep(time.Millisecond * 10)
// // Write request
// txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
// request, err := rpctypes.MapToRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes})
// if err != nil {
// cmn.Exit("cannot encode request: " + err.Error())
// }
// reqBytes := wire.JSONBytes(request)
// //fmt.Print(".")
// err = ws.WriteMessage(websocket.TextMessage, reqBytes)
// if err != nil {
// cmn.Exit("writing websocket request: " + err.Error())
// }
// }
randA := cmn.RandInt() % len(privAccounts)
randB := cmn.RandInt() % len(privAccounts)
if randA == randB {
continue
}
// // Now send coins between these accounts
// for {
// counter += 1
// time.Sleep(time.Millisecond * 10)
privAccountA := privAccounts[randA]
privAccountASequence := privAccountSequences[privAccountA.Account.PubKey.KeyString()]
privAccountSequences[privAccountA.Account.PubKey.KeyString()] = privAccountASequence + 1
privAccountB := privAccounts[randB]
// randA := cmn.RandInt() % len(privAccounts)
// randB := cmn.RandInt() % len(privAccounts)
// if randA == randB {
// continue
// }
tx := &types.SendTx{
Inputs: []types.TxInput{
types.TxInput{
Address: privAccountA.Account.PubKey.Address(),
PubKey: privAccountA.Account.PubKey,
Coins: types.Coins{{"", 3}},
Sequence: privAccountASequence + 1,
},
},
Outputs: []types.TxOutput{
types.TxOutput{
Address: privAccountB.Account.PubKey.Address(),
Coins: types.Coins{{"", 1}},
},
},
}
// privAccountA := privAccounts[randA]
// privAccountASequence := privAccountSequences[privAccountA.Account.PubKey.KeyString()]
// privAccountSequences[privAccountA.Account.PubKey.KeyString()] = privAccountASequence + 1
// privAccountB := privAccounts[randB]
// Sign request
signBytes := tx.SignBytes(chainID)
sig := privAccountA.Sign(signBytes)
tx.Inputs[0].Signature = sig
//fmt.Println("tx:", tx)
// tx := &types.SendTx{
// Inputs: []types.TxInput{
// types.TxInput{
// Address: privAccountA.Account.PubKey.Address(),
// PubKey: privAccountA.Account.PubKey,
// Coins: types.Coins{{"", 3}},
// Sequence: privAccountASequence + 1,
// },
// },
// Outputs: []types.TxOutput{
// types.TxOutput{
// Address: privAccountB.Account.PubKey.Address(),
// Coins: types.Coins{{"", 1}},
// },
// },
// }
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
request, err := rpctypes.MapToRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes})
if err != nil {
cmn.Exit("cannot encode request: " + err.Error())
}
reqBytes := wire.JSONBytes(request)
//fmt.Print(".")
err = ws.WriteMessage(websocket.TextMessage, reqBytes)
if err != nil {
cmn.Exit("writing websocket request: " + err.Error())
}
}
// // Sign request
// signBytes := tx.SignBytes(chainID)
// sig := privAccountA.Sign(signBytes)
// tx.Inputs[0].Signature = sig
// //fmt.Println("tx:", tx)
ws.Stop()
}
// // Write request
// txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
// request, err := rpctypes.MapToRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes})
// if err != nil {
// cmn.Exit("cannot encode request: " + err.Error())
// }
// reqBytes := wire.JSONBytes(request)
// //fmt.Print(".")
// err = ws.WriteMessage(websocket.TextMessage, reqBytes)
// if err != nil {
// cmn.Exit("writing websocket request: " + err.Error())
// }
// }
// ws.Stop()
// }

View File

@ -1,75 +0,0 @@
package types
import (
"fmt"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
)
type Account struct {
PubKey crypto.PubKey `json:"pub_key"` // May be nil, if not known.
Sequence int `json:"sequence"`
Balance Coins `json:"coins"`
}
func (acc *Account) Copy() *Account {
if acc == nil {
return nil
}
accCopy := *acc
return &accCopy
}
func (acc *Account) String() string {
if acc == nil {
return "nil-Account"
}
return fmt.Sprintf("Account{%v %v %v}",
acc.PubKey, acc.Sequence, acc.Balance)
}
//----------------------------------------
type PrivAccount struct {
crypto.PrivKey
Account
}
//----------------------------------------
type AccountGetter interface {
GetAccount(addr []byte) *Account
}
type AccountSetter interface {
SetAccount(addr []byte, acc *Account)
}
type AccountGetterSetter interface {
GetAccount(addr []byte) *Account
SetAccount(addr []byte, acc *Account)
}
func AccountKey(addr []byte) []byte {
return append([]byte("base/a/"), addr...)
}
func GetAccount(store KVStore, addr []byte) *Account {
data := store.Get(AccountKey(addr))
if len(data) == 0 {
return nil
}
var acc *Account
err := wire.ReadBinaryBytes(data, &acc)
if err != nil {
panic(fmt.Sprintf("Error reading account %X error: %v",
data, err.Error()))
}
return acc
}
func SetAccount(store KVStore, addr []byte, acc *Account) {
accBytes := wire.BinaryBytes(acc)
store.Set(AccountKey(addr), accBytes)
}

View File

@ -1,23 +0,0 @@
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNilAccount(t *testing.T) {
var acc Account
//test Copy
accCopy := acc.Copy()
//note that the assert.True is used instead of assert.Equal because looking at pointers
assert.True(t, &acc != accCopy, "Account Copy Error, acc1: %v, acc2: %v", &acc, accCopy)
assert.Equal(t, acc.Sequence, accCopy.Sequence)
//test sending nils for panic
var nilAcc *Account
nilAcc.String()
nilAcc.Copy()
}

View File

@ -1,71 +0,0 @@
package types
import (
"fmt"
abci "github.com/tendermint/abci/types"
)
type Plugin interface {
// Name of this plugin, should be short.
Name() string
// Run a transaction from ABCI DeliverTx
RunTx(store KVStore, ctx CallContext, txBytes []byte) (res abci.Result)
// Other ABCI message handlers
SetOption(store KVStore, key, value string) (log string)
InitChain(store KVStore, vals []*abci.Validator)
BeginBlock(store KVStore, hash []byte, header *abci.Header)
EndBlock(store KVStore, height uint64) abci.ResponseEndBlock
}
//----------------------------------------
type CallContext struct {
CallerAddress []byte // Caller's Address (hash of PubKey)
CallerAccount *Account // Caller's Account, w/ fee & TxInputs deducted
Coins Coins // The coins that the caller wishes to spend, excluding fees
}
func NewCallContext(callerAddress []byte, callerAccount *Account, coins Coins) CallContext {
return CallContext{
CallerAddress: callerAddress,
CallerAccount: callerAccount,
Coins: coins,
}
}
//----------------------------------------
type Plugins struct {
byName map[string]Plugin
plist []Plugin
}
func NewPlugins() *Plugins {
return &Plugins{
byName: make(map[string]Plugin),
}
}
func (pgz *Plugins) RegisterPlugin(plugin Plugin) {
name := plugin.Name()
if name == "" {
panic("Plugin name cannot be blank")
}
if _, exists := pgz.byName[name]; exists {
panic(fmt.Sprintf("Plugin already exists by the name of %v", name))
}
pgz.byName[name] = plugin
pgz.plist = append(pgz.plist, plugin)
}
func (pgz *Plugins) GetByName(name string) Plugin {
return pgz.byName[name]
}
func (pgz *Plugins) GetList() []Plugin {
return pgz.plist
}

View File

@ -1,41 +0,0 @@
package types
import (
"testing"
"github.com/stretchr/testify/assert"
abci "github.com/tendermint/abci/types"
)
//----------------------------------
type Dummy struct{}
func (d *Dummy) Name() string {
return "dummy"
}
func (d *Dummy) RunTx(store KVStore, ctx CallContext, txBytes []byte) (res abci.Result) {
return
}
func (d *Dummy) SetOption(storei KVStore, key, value string) (log string) {
return ""
}
func (d *Dummy) InitChain(store KVStore, vals []*abci.Validator) {
}
func (d *Dummy) BeginBlock(store KVStore, hash []byte, header *abci.Header) {
}
func (d *Dummy) EndBlock(store KVStore, height uint64) (res abci.ResponseEndBlock) {
return
}
//----------------------------------
func TestPlugin(t *testing.T) {
assert := assert.New(t)
plugins := NewPlugins()
assert.Zero(len(plugins.GetList()), "plugins object init with a objects")
plugins.RegisterPlugin(&Dummy{})
assert.Equal(len(plugins.GetList()), 1, "plugin wasn't added to plist after registered")
assert.Equal(plugins.GetByName("dummy").Name(), "dummy", "plugin wasn't retrieved properly with GetByName")
}

View File

@ -1,105 +1,105 @@
package types
// Helper functions for testing
// // Helper functions for testing
import (
"github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common"
)
// import (
// "github.com/tendermint/go-crypto"
// cmn "github.com/tendermint/tmlibs/common"
// )
// Creates a PrivAccount from secret.
// The amount is not set.
func PrivAccountFromSecret(secret string) PrivAccount {
privKey :=
crypto.GenPrivKeyEd25519FromSecret([]byte(secret)).Wrap()
privAccount := PrivAccount{
PrivKey: privKey,
Account: Account{
PubKey: privKey.PubKey(),
},
}
return privAccount
}
// // Creates a PrivAccount from secret.
// // The amount is not set.
// func PrivAccountFromSecret(secret string) PrivAccount {
// privKey :=
// crypto.GenPrivKeyEd25519FromSecret([]byte(secret)).Wrap()
// privAccount := PrivAccount{
// PrivKey: privKey,
// Account: Account{
// PubKey: privKey.PubKey(),
// },
// }
// return privAccount
// }
// Make `num` random accounts
func RandAccounts(num int, minAmount int64, maxAmount int64) []PrivAccount {
privAccs := make([]PrivAccount, num)
for i := 0; i < num; i++ {
// // Make `num` random accounts
// func RandAccounts(num int, minAmount int64, maxAmount int64) []PrivAccount {
// privAccs := make([]PrivAccount, num)
// for i := 0; i < num; i++ {
balance := minAmount
if maxAmount > minAmount {
balance += cmn.RandInt64() % (maxAmount - minAmount)
}
// balance := minAmount
// if maxAmount > minAmount {
// balance += cmn.RandInt64() % (maxAmount - minAmount)
// }
privKey := crypto.GenPrivKeyEd25519().Wrap()
pubKey := privKey.PubKey()
privAccs[i] = PrivAccount{
PrivKey: privKey,
Account: Account{
PubKey: pubKey,
Balance: Coins{Coin{"", balance}},
},
}
}
// privKey := crypto.GenPrivKeyEd25519().Wrap()
// pubKey := privKey.PubKey()
// privAccs[i] = PrivAccount{
// PrivKey: privKey,
// Account: Account{
// PubKey: pubKey,
// Balance: Coins{Coin{"", balance}},
// },
// }
// }
return privAccs
}
// return privAccs
// }
/////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////
//func MakeAccs(secrets ...string) (accs []PrivAccount) {
// for _, secret := range secrets {
// privAcc := PrivAccountFromSecret(secret)
// privAcc.Account.Balance = Coins{{"mycoin", 7}}
// accs = append(accs, privAcc)
// }
// return
//}
// //func MakeAccs(secrets ...string) (accs []PrivAccount) {
// // for _, secret := range secrets {
// // privAcc := PrivAccountFromSecret(secret)
// // privAcc.Account.Balance = Coins{{"mycoin", 7}}
// // accs = append(accs, privAcc)
// // }
// // return
// //}
func MakeAcc(secret string) PrivAccount {
privAcc := PrivAccountFromSecret(secret)
privAcc.Account.Balance = Coins{{"mycoin", 7}}
return privAcc
}
// func MakeAcc(secret string) PrivAccount {
// privAcc := PrivAccountFromSecret(secret)
// privAcc.Account.Balance = Coins{{"mycoin", 7}}
// return privAcc
// }
func Accs2TxInputs(seq int, accs ...PrivAccount) []TxInput {
var txs []TxInput
for _, acc := range accs {
tx := NewTxInput(
acc.Account.PubKey,
Coins{{"mycoin", 5}},
seq)
txs = append(txs, tx)
}
return txs
}
// func Accs2TxInputs(seq int, accs ...PrivAccount) []TxInput {
// var txs []TxInput
// for _, acc := range accs {
// tx := NewTxInput(
// acc.Account.PubKey,
// Coins{{"mycoin", 5}},
// seq)
// txs = append(txs, tx)
// }
// return txs
// }
//turn a list of accounts into basic list of transaction outputs
func Accs2TxOutputs(accs ...PrivAccount) []TxOutput {
var txs []TxOutput
for _, acc := range accs {
tx := TxOutput{
acc.Account.PubKey.Address(),
Coins{{"mycoin", 4}}}
txs = append(txs, tx)
}
return txs
}
// //turn a list of accounts into basic list of transaction outputs
// func Accs2TxOutputs(accs ...PrivAccount) []TxOutput {
// var txs []TxOutput
// for _, acc := range accs {
// tx := TxOutput{
// acc.Account.PubKey.Address(),
// Coins{{"mycoin", 4}}}
// txs = append(txs, tx)
// }
// return txs
// }
func MakeSendTx(seq int, accOut PrivAccount, accsIn ...PrivAccount) *SendTx {
tx := &SendTx{
Gas: 0,
Fee: Coin{"mycoin", 1},
Inputs: Accs2TxInputs(seq, accsIn...),
Outputs: Accs2TxOutputs(accOut),
}
// func MakeSendTx(seq int, accOut PrivAccount, accsIn ...PrivAccount) *SendTx {
// tx := &SendTx{
// Gas: 0,
// Fee: Coin{"mycoin", 1},
// Inputs: Accs2TxInputs(seq, accsIn...),
// Outputs: Accs2TxOutputs(accOut),
// }
return tx
}
// return tx
// }
func SignTx(chainID string, tx *SendTx, accs ...PrivAccount) {
signBytes := tx.SignBytes(chainID)
for i, _ := range tx.Inputs {
tx.Inputs[i].Signature = accs[i].Sign(signBytes)
}
}
// func SignTx(chainID string, tx *SendTx, accs ...PrivAccount) {
// signBytes := tx.SignBytes(chainID)
// for i, _ := range tx.Inputs {
// tx.Inputs[i].Signature = accs[i].Sign(signBytes)
// }
// }

View File

@ -1,240 +0,0 @@
package types
import (
"bytes"
"encoding/json"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
"github.com/tendermint/go-wire/data"
. "github.com/tendermint/tmlibs/common"
)
/*
Tx (Transaction) is an atomic operation on the ledger state.
Account Types:
- SendTx Send coins to address
- AppTx Send a msg to a contract that runs in the vm
*/
type Tx interface {
AssertIsTx()
SignBytes(chainID string) []byte
}
// Types of Tx implementations
const (
// Account transactions
TxTypeSend = byte(0x01)
TxTypeApp = byte(0x02)
TxNameSend = "send"
TxNameApp = "app"
)
func (_ *SendTx) AssertIsTx() {}
func (_ *AppTx) AssertIsTx() {}
var txMapper data.Mapper
// register both private key types with go-wire/data (and thus go-wire)
func init() {
txMapper = data.NewMapper(TxS{}).
RegisterImplementation(&SendTx{}, TxNameSend, TxTypeSend).
RegisterImplementation(&AppTx{}, TxNameApp, TxTypeApp)
}
// TxS add json serialization to Tx
type TxS struct {
Tx `json:"unwrap"`
}
func (p TxS) MarshalJSON() ([]byte, error) {
return txMapper.ToJSON(p.Tx)
}
func (p *TxS) UnmarshalJSON(data []byte) (err error) {
parsed, err := txMapper.FromJSON(data)
if err == nil {
p.Tx = parsed.(Tx)
}
return
}
//-----------------------------------------------------------------------------
type TxInput struct {
Address data.Bytes `json:"address"` // Hash of the PubKey
Coins Coins `json:"coins"` //
Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput
Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx
PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0
}
func (txIn TxInput) ValidateBasic() abci.Result {
if len(txIn.Address) != 20 {
return abci.ErrBaseInvalidInput.AppendLog("Invalid address length")
}
if !txIn.Coins.IsValid() {
return abci.ErrBaseInvalidInput.AppendLog(Fmt("Invalid coins %v", txIn.Coins))
}
if txIn.Coins.IsZero() {
return abci.ErrBaseInvalidInput.AppendLog("Coins cannot be zero")
}
if txIn.Sequence <= 0 {
return abci.ErrBaseInvalidInput.AppendLog("Sequence must be greater than 0")
}
if txIn.Sequence == 1 && txIn.PubKey.Empty() {
return abci.ErrBaseInvalidInput.AppendLog("PubKey must be present when Sequence == 1")
}
if txIn.Sequence > 1 && !txIn.PubKey.Empty() {
return abci.ErrBaseInvalidInput.AppendLog("PubKey must be nil when Sequence > 1")
}
return abci.OK
}
func (txIn TxInput) String() string {
return Fmt("TxInput{%X,%v,%v,%v,%v}", txIn.Address, txIn.Coins, txIn.Sequence, txIn.Signature, txIn.PubKey)
}
func NewTxInput(pubKey crypto.PubKey, coins Coins, sequence int) TxInput {
input := TxInput{
Address: pubKey.Address(),
Coins: coins,
Sequence: sequence,
}
if sequence == 1 {
input.PubKey = pubKey
}
return input
}
//-----------------------------------------------------------------------------
type TxOutput struct {
Address data.Bytes `json:"address"` // Hash of the PubKey
Coins Coins `json:"coins"` //
}
// An output destined for another chain may be formatted as `chainID/address`.
// ChainAndAddress returns the chainID prefix and the address.
// If there is no chainID prefix, the first returned value is nil.
func (txOut TxOutput) ChainAndAddress() ([]byte, []byte, abci.Result) {
var chainPrefix []byte
address := txOut.Address
if len(address) > 20 {
spl := bytes.SplitN(address, []byte("/"), 2)
if len(spl) != 2 {
return nil, nil, abci.ErrBaseInvalidOutput.AppendLog("Invalid address format")
}
chainPrefix = spl[0]
address = spl[1]
}
if len(address) != 20 {
return nil, nil, abci.ErrBaseInvalidOutput.AppendLog("Invalid address length")
}
return chainPrefix, address, abci.OK
}
func (txOut TxOutput) ValidateBasic() abci.Result {
_, _, r := txOut.ChainAndAddress()
if r.IsErr() {
return r
}
if !txOut.Coins.IsValid() {
return abci.ErrBaseInvalidOutput.AppendLog(Fmt("Invalid coins %v", txOut.Coins))
}
if txOut.Coins.IsZero() {
return abci.ErrBaseInvalidOutput.AppendLog("Coins cannot be zero")
}
return abci.OK
}
func (txOut TxOutput) String() string {
return Fmt("TxOutput{%X,%v}", txOut.Address, txOut.Coins)
}
//-----------------------------------------------------------------------------
type SendTx struct {
Gas int64 `json:"gas"` // Gas
Fee Coin `json:"fee"` // Fee
Inputs []TxInput `json:"inputs"`
Outputs []TxOutput `json:"outputs"`
}
func (tx *SendTx) SignBytes(chainID string) []byte {
signBytes := wire.BinaryBytes(chainID)
sigz := make([]crypto.Signature, len(tx.Inputs))
for i := range tx.Inputs {
sigz[i] = tx.Inputs[i].Signature
tx.Inputs[i].Signature = crypto.Signature{}
}
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
for i := range tx.Inputs {
tx.Inputs[i].Signature = sigz[i]
}
return signBytes
}
func (tx *SendTx) SetSignature(addr []byte, sig crypto.Signature) bool {
for i, input := range tx.Inputs {
if bytes.Equal(input.Address, addr) {
tx.Inputs[i].Signature = sig
return true
}
}
return false
}
func (tx *SendTx) String() string {
return Fmt("SendTx{%v/%v %v->%v}", tx.Gas, tx.Fee, tx.Inputs, tx.Outputs)
}
//-----------------------------------------------------------------------------
type AppTx struct {
Gas int64 `json:"gas"` // Gas
Fee Coin `json:"fee"` // Fee
Name string `json:"type"` // Which plugin
Input TxInput `json:"input"` // Hmmm do we want coins?
Data json.RawMessage `json:"data"`
}
func (tx *AppTx) SignBytes(chainID string) []byte {
signBytes := wire.BinaryBytes(chainID)
sig := tx.Input.Signature
tx.Input.Signature = crypto.Signature{}
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
tx.Input.Signature = sig
return signBytes
}
func (tx *AppTx) SetSignature(sig crypto.Signature) bool {
tx.Input.Signature = sig
return true
}
func (tx *AppTx) String() string {
return Fmt("AppTx{%v/%v %v %v %X}", tx.Gas, tx.Fee, tx.Name, tx.Input, tx.Data)
}
//-----------------------------------------------------------------------------
func TxID(chainID string, tx Tx) []byte {
signBytes := tx.SignBytes(chainID)
return wire.BinaryRipemd160(signBytes)
}
//--------------------------------------------------------------------------------
// Contract: This function is deterministic and completely reversible.
func jsonEscape(str string) string {
escapedBytes, err := json.Marshal(str)
if err != nil {
PanicSanity(Fmt("Error json-escaping a string", str))
}
return string(escapedBytes)
}

View File

@ -1,177 +0,0 @@
package types
import (
"encoding/hex"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
data "github.com/tendermint/go-wire/data"
)
var chainID string = "test_chain"
func TestSendTxSignable(t *testing.T) {
sendTx := &SendTx{
Gas: 222,
Fee: Coin{"", 111},
Inputs: []TxInput{
TxInput{
Address: []byte("input1"),
Coins: Coins{{"", 12345}},
Sequence: 67890,
},
TxInput{
Address: []byte("input2"),
Coins: Coins{{"", 111}},
Sequence: 222,
},
},
Outputs: []TxOutput{
TxOutput{
Address: []byte("output1"),
Coins: Coins{{"", 333}},
},
TxOutput{
Address: []byte("output2"),
Coins: Coins{{"", 444}},
},
},
}
signBytes := sendTx.SignBytes(chainID)
signBytesHex := fmt.Sprintf("%X", signBytes)
expected := "010A746573745F636861696E0100000000000000DE00000000000000006F01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC"
assert.Equal(t, signBytesHex, expected,
"Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)
}
func TestAppTxSignable(t *testing.T) {
callTx := &AppTx{
Gas: 222,
Fee: Coin{"", 111},
Name: "X",
Input: TxInput{
Address: []byte("input1"),
Coins: Coins{{"", 12345}},
Sequence: 67890,
},
Data: []byte("data1"),
}
signBytes := callTx.SignBytes(chainID)
signBytesHex := fmt.Sprintf("%X", signBytes)
expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131"
assert.Equal(t, signBytesHex, expected,
"Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)
}
func TestSendTxJSON(t *testing.T) {
assert, require := assert.New(t), require.New(t)
chainID := "test_chain_id"
test1PrivAcc := PrivAccountFromSecret("sendtx1")
test2PrivAcc := PrivAccountFromSecret("sendtx2")
// Construct a SendTx signature
tx := &SendTx{
Gas: 1,
Fee: Coin{"foo", 2},
Inputs: []TxInput{
NewTxInput(test1PrivAcc.PubKey, Coins{{"foo", 10}}, 1),
},
Outputs: []TxOutput{
TxOutput{
Address: test2PrivAcc.PubKey.Address(),
Coins: Coins{{"foo", 8}},
},
},
}
// serialize this as json and back
js, err := data.ToJSON(TxS{tx})
require.Nil(err)
// fmt.Println(string(js))
txs := TxS{}
err = data.FromJSON(js, &txs)
require.Nil(err)
tx2, ok := txs.Tx.(*SendTx)
require.True(ok)
// make sure they are the same!
signBytes := tx.SignBytes(chainID)
signBytes2 := tx2.SignBytes(chainID)
assert.Equal(signBytes, signBytes2)
assert.Equal(tx, tx2)
// sign this thing
sig := test1PrivAcc.Sign(signBytes)
// we handle both raw sig and wrapped sig the same
tx.SetSignature(test1PrivAcc.PubKey.Address(), sig)
tx2.SetSignature(test1PrivAcc.PubKey.Address(), sig)
assert.Equal(tx, tx2)
// let's marshal / unmarshal this with signature
js, err = data.ToJSON(TxS{tx})
require.Nil(err)
// fmt.Println(string(js))
err = data.FromJSON(js, &txs)
require.Nil(err)
tx2, ok = txs.Tx.(*SendTx)
require.True(ok)
// and make sure the sig is preserved
assert.Equal(tx, tx2)
assert.False(tx2.Inputs[0].Signature.Empty())
}
func TestSendTxIBC(t *testing.T) {
assert, require := assert.New(t), require.New(t)
good, err := hex.DecodeString("1960CA7E170862837AA8F22A947194F41F61860B")
require.Nil(err)
short, err := hex.DecodeString("1960CA7E170862837AA8F22F947194F41F610B")
require.Nil(err)
long, err := hex.DecodeString("1960CA7E170862837AA8F22F947194F41F6186120B")
require.Nil(err)
slash, err := hex.DecodeString("F40ECECEA86F29D0FDF2980EF72F1708687BD4BF")
require.Nil(err)
coins := Coins{{"atom", 5}}
addrs := []struct {
addr []byte
valid bool
}{
{good, true},
{slash, true},
{long, false},
{short, false},
}
prefixes := []struct {
prefix []byte
valid bool
}{
{nil, true},
{[]byte("chain-1/"), true},
{[]byte("chain/with/paths/"), false},
{[]byte("no-slash-here"), false},
}
for i, tc := range addrs {
for j, pc := range prefixes {
addr := append(pc.prefix, tc.addr...)
output := TxOutput{Address: addr, Coins: coins}
res := output.ValidateBasic()
if tc.valid && pc.valid {
assert.True(res.IsOK(), "%d,%d: %s", i, j, res.Log)
} else {
assert.False(res.IsOK(), "%d,%d: %s", i, j, res.Log)
}
}
}
}