Vote->Counter; Fee is types.Coin; Context has Account; Cleanup

This commit is contained in:
Jae Kwon 2017-01-15 15:10:51 -08:00
parent 5ba8250efd
commit 16a6680e24
14 changed files with 319 additions and 286 deletions

View File

@ -41,8 +41,8 @@ func (app *Basecoin) Info() abci.ResponseInfo {
return abci.ResponseInfo{Data: Fmt("Basecoin v%v", version)}
}
func (app *Basecoin) RegisterPlugin(name string, plugin types.Plugin) {
app.plugins.RegisterPlugin(name, plugin)
func (app *Basecoin) RegisterPlugin(plugin types.Plugin) {
app.plugins.RegisterPlugin(plugin)
}
// TMSP::SetOption
@ -144,21 +144,21 @@ func (app *Basecoin) Commit() (res abci.Result) {
// TMSP::InitChain
func (app *Basecoin) InitChain(validators []*abci.Validator) {
for _, plugin := range app.plugins.GetList() {
plugin.Plugin.InitChain(app.state, validators)
plugin.InitChain(app.state, validators)
}
}
// TMSP::BeginBlock
func (app *Basecoin) BeginBlock(height uint64) {
for _, plugin := range app.plugins.GetList() {
plugin.Plugin.BeginBlock(app.state, height)
plugin.BeginBlock(app.state, height)
}
}
// TMSP::EndBlock
func (app *Basecoin) EndBlock(height uint64) (diffs []*abci.Validator) {
for _, plugin := range app.plugins.GetList() {
moreDiffs := plugin.Plugin.EndBlock(app.state, height)
moreDiffs := plugin.EndBlock(app.state, height)
diffs = append(diffs, moreDiffs...)
}
return

View File

@ -3,9 +3,9 @@ package app
import (
"testing"
cmn "github.com/tendermint/basecoin/common"
"github.com/tendermint/basecoin/testutils"
"github.com/tendermint/basecoin/types"
. "github.com/tendermint/go-common"
cmn "github.com/tendermint/go-common"
"github.com/tendermint/go-wire"
eyescli "github.com/tendermint/merkleeyes/client"
)
@ -17,8 +17,8 @@ func TestSendTx(t *testing.T) {
bcApp.SetOption("base/chainID", chainID)
t.Log(bcApp.Info())
test1PrivAcc := cmn.PrivAccountFromSecret("test1")
test2PrivAcc := cmn.PrivAccountFromSecret("test2")
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
test2PrivAcc := testutils.PrivAccountFromSecret("test2")
// Seed Basecoin with account
test1Acc := test1PrivAcc.Account
@ -27,15 +27,15 @@ func TestSendTx(t *testing.T) {
res := bcApp.Commit()
if res.IsErr() {
Exit(Fmt("Failed Commit: %v", res.Error()))
cmn.Exit(cmn.Fmt("Failed Commit: %v", res.Error()))
}
// Construct a SendTx signature
tx := &types.SendTx{
Fee: 0,
Gas: 0,
Fee: types.Coin{"", 0},
Inputs: []types.TxInput{
cmn.MakeInput(test1PrivAcc.Account.PubKey, types.Coins{{"", 1}}, 1),
types.NewTxInput(test1PrivAcc.Account.PubKey, types.Coins{{"", 1}}, 1),
},
Outputs: []types.TxOutput{
types.TxOutput{
@ -57,7 +57,7 @@ func TestSendTx(t *testing.T) {
res = bcApp.DeliverTx(txBytes)
t.Log(res)
if res.IsErr() {
t.Errorf(Fmt("Failed: %v", res.Error()))
t.Errorf("Failed: %v", res.Error())
}
}
@ -69,19 +69,19 @@ func TestSequence(t *testing.T) {
t.Log(bcApp.Info())
// Get the test account
test1PrivAcc := cmn.PrivAccountFromSecret("test1")
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
test1Acc := test1PrivAcc.Account
test1Acc.Balance = types.Coins{{"", 1 << 53}}
t.Log(bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc))))
res := bcApp.Commit()
if res.IsErr() {
t.Errorf(Fmt("Failed Commit: %v", res.Error()))
t.Errorf("Failed Commit: %v", res.Error())
}
sequence := int(1)
// Make a bunch of PrivAccounts
privAccounts := cmn.RandAccounts(1000, 1000000, 0)
privAccounts := testutils.RandAccounts(1000, 1000000, 0)
privAccountSequences := make(map[string]int)
// Send coins to each account
@ -89,10 +89,10 @@ func TestSequence(t *testing.T) {
privAccount := privAccounts[i]
tx := &types.SendTx{
Fee: 2,
Gas: 2,
Fee: types.Coin{"", 2},
Inputs: []types.TxInput{
cmn.MakeInput(test1Acc.PubKey, types.Coins{{"", 1000002}}, sequence),
types.NewTxInput(test1Acc.PubKey, types.Coins{{"", 1000002}}, sequence),
},
Outputs: []types.TxOutput{
types.TxOutput{
@ -122,13 +122,13 @@ func TestSequence(t *testing.T) {
res = bcApp.Commit()
if res.IsErr() {
t.Errorf(Fmt("Failed Commit: %v", res.Error()))
t.Errorf("Failed Commit: %v", res.Error())
}
// Now send coins between these accounts
for i := 0; i < 10000; i++ {
randA := RandInt() % len(privAccounts)
randB := RandInt() % len(privAccounts)
randA := cmn.RandInt() % len(privAccounts)
randB := cmn.RandInt() % len(privAccounts)
if randA == randB {
continue
}
@ -139,10 +139,10 @@ func TestSequence(t *testing.T) {
privAccountB := privAccounts[randB]
tx := &types.SendTx{
Fee: 2,
Gas: 2,
Fee: types.Coin{"", 2},
Inputs: []types.TxInput{
cmn.MakeInput(privAccountA.Account.PubKey, types.Coins{{"", 3}}, privAccountASequence+1),
types.NewTxInput(privAccountA.Account.PubKey, types.Coins{{"", 3}}, privAccountASequence+1),
},
Outputs: []types.TxOutput{
types.TxOutput{

26
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348
updated: 2017-01-14T20:46:16.999965963-08:00
updated: 2017-01-15T14:45:40.368426139-08:00
imports:
- name: github.com/btcsuite/btcd
version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8
@ -41,7 +41,7 @@ imports:
- leveldb/table
- leveldb/util
- name: github.com/tendermint/abci
version: 6526ab2137fadd0f4d2e25002bbfc1784b4f3c27
version: 05096de3687ac582bec63860b3dd384acd9149aa
subpackages:
- client
- server
@ -68,9 +68,9 @@ imports:
- name: github.com/tendermint/go-logger
version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2
- name: github.com/tendermint/go-merkle
version: 1bc9a24706d715cd45403593c6d0a870d70011bb
version: 2979c7eb8aa020fa1cf203654907dbb889703888
- name: github.com/tendermint/go-p2p
version: eab2baa363de01b052b88c559e803776cd2c7dd6
version: 67c9086b7458eb45b1970483decd01cd744c477a
subpackages:
- upnp
- name: github.com/tendermint/go-rpc
@ -85,12 +85,12 @@ imports:
subpackages:
- term
- name: github.com/tendermint/merkleeyes
version: db66769b34a950bb588919c94925724f21583925
version: 2cf87e5f049ab6131aa4ea188c1b5b629d9b3bf9
subpackages:
- app
- client
- name: github.com/tendermint/tendermint
version: 0aecfe2dae3269a9450b5d8b3bac8721a8dde7c7
version: cf0cb9558aaecbf3ddb071eb863df77e55d828ed
subpackages:
- rpc/core/types
- types
@ -131,4 +131,16 @@ imports:
- stats
- tap
- transport
testImports: []
testImports:
- name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
subpackages:
- spew
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
- difflib
- name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages:
- assert

102
plugins/counter/counter.go Normal file
View File

@ -0,0 +1,102 @@
package counter
import (
"fmt"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/types"
"github.com/tendermint/go-wire"
)
type CounterPluginState struct {
Counter int
TotalCost types.Coins
}
type CounterTx struct {
Valid bool
Cost types.Coins
}
//--------------------------------------------------------------------------------
type CounterPlugin struct {
name string
}
func (cp *CounterPlugin) Name() string {
return cp.name
}
func (cp *CounterPlugin) StateKey() []byte {
return []byte(fmt.Sprintf("CounterPlugin{name=%v}.State", cp.name))
}
func NewCounterPlugin(name string) *CounterPlugin {
return &CounterPlugin{
name: name,
}
}
func (cp *CounterPlugin) SetOption(store types.KVStore, key string, value string) (log string) {
return ""
}
func (cp *CounterPlugin) RunTx(store types.KVStore, ctx types.CallContext, txBytes []byte) (res abci.Result) {
// Decode tx
var tx CounterTx
err := wire.ReadBinaryBytes(txBytes, &tx)
if err != nil {
return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error())
}
// Validate tx
if !tx.Valid {
return abci.ErrInternalError.AppendLog("CounterTx.Valid must be true")
}
if !tx.Cost.IsValid() {
return abci.ErrInternalError.AppendLog("CounterTx.Cost is not sorted or has zero amounts")
}
if !tx.Cost.IsNonnegative() {
return abci.ErrInternalError.AppendLog("CounterTx.Cost must be nonnegative")
}
// Did the caller provide enough coins?
if !ctx.Coins.IsGTE(tx.Cost) {
return abci.ErrInsufficientFunds.AppendLog("CounterTx.Cost was not provided")
}
// TODO If there are any funds left over, return funds.
// e.g. !ctx.Coins.Minus(tx.Cost).IsZero()
// ctx.CallerAccount is synced w/ store, so just modify that and store it.
// Load CounterPluginState
var cpState CounterPluginState
cpStateBytes := store.Get(cp.StateKey())
if len(cpStateBytes) > 0 {
err = wire.ReadBinaryBytes(cpStateBytes, &cpState)
if err != nil {
return abci.ErrInternalError.AppendLog("Error decoding state: " + err.Error())
}
}
// Update CounterPluginState
cpState.Counter += 1
cpState.TotalCost = cpState.TotalCost.Plus(tx.Cost)
// Save CounterPluginState
store.Set(cp.StateKey(), wire.BinaryBytes(cpState))
return abci.OK
}
func (cp *CounterPlugin) InitChain(store types.KVStore, vals []*abci.Validator) {
}
func (cp *CounterPlugin) BeginBlock(store types.KVStore, height uint64) {
}
func (cp *CounterPlugin) EndBlock(store types.KVStore, height uint64) []*abci.Validator {
return nil
}

View File

@ -0,0 +1,99 @@
package counter
import (
"testing"
"github.com/stretchr/testify/assert"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/app"
"github.com/tendermint/basecoin/testutils"
"github.com/tendermint/basecoin/types"
"github.com/tendermint/go-wire"
eyescli "github.com/tendermint/merkleeyes/client"
)
func TestCounterPlugin(t *testing.T) {
// Basecoin initialization
eyesCli := eyescli.NewLocalClient()
chainID := "test_chain_id"
bcApp := app.NewBasecoin(eyesCli)
bcApp.SetOption("base/chainID", chainID)
t.Log(bcApp.Info())
// Add Counter plugin
counterPluginName := "testcounter"
counterPlugin := NewCounterPlugin(counterPluginName)
bcApp.RegisterPlugin(counterPlugin)
// Account initialization
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
// Seed Basecoin with account
test1Acc := test1PrivAcc.Account
test1Acc.Balance = types.Coins{{"", 1000}, {"gold", 1000}}
bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc)))
// Deliver a CounterTx
DeliverCounterTx := func(gas int64, fee types.Coin, inputCoins types.Coins, inputSequence int, cost types.Coins) abci.Result {
// Construct an AppTx signature
tx := &types.AppTx{
Gas: gas,
Fee: fee,
Name: counterPluginName,
Input: types.NewTxInput(test1Acc.PubKey, inputCoins, inputSequence),
Data: wire.BinaryBytes(CounterTx{Valid: true, Cost: cost}),
}
// Sign request
signBytes := tx.SignBytes(chainID)
t.Logf("Sign bytes: %X\n", signBytes)
sig := test1PrivAcc.PrivKey.Sign(signBytes)
tx.Input.Signature = sig
t.Logf("Signed TX bytes: %X\n", wire.BinaryBytes(struct{ types.Tx }{tx}))
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
return bcApp.DeliverTx(txBytes)
}
// REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, cost) {
// Test a basic send, no fee
res := DeliverCounterTx(0, types.Coin{}, types.Coins{{"", 1}}, 1, types.Coins{})
assert.True(t, res.IsOK(), res.String())
// Test fee prevented transaction
res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 1}}, 2, types.Coins{})
assert.True(t, res.IsErr(), res.String())
// Test input equals fee
res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 2}}, 2, types.Coins{})
assert.True(t, res.IsOK(), res.String())
// Test more input than fee
res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 3}}, 3, types.Coins{})
assert.True(t, res.IsOK(), res.String())
// Test input equals fee+cost
res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 4, types.Coins{{"", 2}, {"gold", 1}})
assert.True(t, res.IsOK(), res.String())
// Test fee+cost prevented transaction, not enough ""
res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 2}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 1}})
assert.True(t, res.IsErr(), res.String())
// Test fee+cost prevented transaction, not enough "gold"
res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 2}})
assert.True(t, res.IsErr(), res.String())
// Test more input than fee, more ""
res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 4}, {"gold", 1}}, 6, types.Coins{{"", 2}, {"gold", 1}})
assert.True(t, res.IsOK(), res.String())
// Test more input than fee, more "gold"
res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 2}}, 7, types.Coins{{"", 2}, {"gold", 1}})
assert.True(t, res.IsOK(), res.String())
// REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, cost) {
}

View File

@ -1,92 +0,0 @@
package vote
import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/types"
"github.com/tendermint/go-wire"
)
type Vote struct {
bb *ballotBox
}
type ballotBox struct {
issue string
votesYes int
votesNo int
}
type Tx struct {
voteYes bool
}
func NewVoteInstance(issue string) Vote {
return Vote{
&ballotBox{
issue: issue,
votesYes: 0,
votesNo: 0,
},
}
}
func (app Vote) SetOption(store types.KVStore, key string, value string) (log string) {
return ""
}
//because no coins are being exchanged ctx is unused
func (app Vote) RunTx(store types.KVStore, ctx types.CallContext, txBytes []byte) (res abci.Result) {
// Decode tx
var tx Tx
err := wire.ReadBinaryBytes(txBytes, &tx)
if err != nil {
return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error())
}
//Read the ballotBox from the store
kvBytes := store.Get([]byte(app.bb.issue))
var tempBB ballotBox
//does the issue already exist?
if kvBytes != nil {
err := wire.ReadBinaryBytes(kvBytes, &tempBB)
if err != nil {
return abci.ErrBaseEncodingError.AppendLog("Error decoding BallotBox: " + err.Error())
}
} else {
//TODO add extra fee for opening new issue
tempBB = ballotBox{
issue: app.bb.issue,
votesYes: 0,
votesNo: 0,
}
issueBytes := wire.BinaryBytes(struct{ ballotBox }{tempBB})
store.Set([]byte(app.bb.issue), issueBytes)
}
//Write the updated ballotBox to the store
if tx.voteYes {
tempBB.votesYes += 1
} else {
tempBB.votesNo += 1
}
issueBytes := wire.BinaryBytes(struct{ ballotBox }{tempBB})
store.Set([]byte(app.bb.issue), issueBytes)
return abci.OK
}
//unused
func (app Vote) InitChain(store types.KVStore, vals []*abci.Validator) {
}
func (app Vote) BeginBlock(store types.KVStore, height uint64) {
}
func (app Vote) EndBlock(store types.KVStore, height uint64) []*abci.Validator {
var diffs []*abci.Validator
return diffs
}

View File

@ -1,100 +0,0 @@
package vote
import (
"fmt"
"testing"
"github.com/tendermint/basecoin/app"
cmn "github.com/tendermint/basecoin/common"
"github.com/tendermint/basecoin/types"
. "github.com/tendermint/go-common"
"github.com/tendermint/go-wire"
eyescli "github.com/tendermint/merkleeyes/client"
)
const PluginNameVote = "vote"
func TestVote(t *testing.T) {
//base initialization
eyesCli := eyescli.NewLocalClient()
chainID := "test_chain_id"
bcApp := app.NewBasecoin(eyesCli)
bcApp.SetOption("base/chainID", chainID)
fmt.Println(bcApp.Info())
//account initialization
test1PrivAcc := cmn.PrivAccountFromSecret("test1")
// Seed Basecoin with account
test1Acc := test1PrivAcc.Account
test1Acc.Balance = types.Coins{{"", 1000}}
fmt.Println(bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc))))
//vote initialization
votePlugin := NewVoteInstance("humanRights")
bcApp.RegisterPlugin(
PluginNameVote,
votePlugin,
)
//commit
res := bcApp.Commit()
if res.IsErr() {
Exit(Fmt("Failed Commit: %v", res.Error()))
}
//transaction sequence number
seqNum := 1
//Construct, Sign, Write function variable
CSW := func(fees, sendCoins int64) {
// Construct an AppTx signature
tx := &types.AppTx{
Fee: fees,
Gas: 0,
Name: PluginNameVote,
Input: cmn.MakeInput(test1Acc.PubKey, types.Coins{{"", sendCoins}}, seqNum),
Data: wire.BinaryBytes(struct{ Tx }{Tx{voteYes: true}}), //a vote for human rights
}
// Sign request
signBytes := tx.SignBytes(chainID)
fmt.Printf("Sign bytes: %X\n", signBytes)
sig := test1PrivAcc.PrivKey.Sign(signBytes)
tx.Input.Signature = sig
fmt.Printf("Signed TX bytes: %X\n", wire.BinaryBytes(struct{ types.Tx }{tx}))
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
res = bcApp.DeliverTx(txBytes)
fmt.Println(res)
if res.IsOK() {
seqNum += 1
}
}
//Test a basic send, no fees
CSW(0, 1)
if res.IsErr() {
Exit(Fmt("Failed: %v", res.Error()))
}
//Test fee prevented transaction
CSW(2, 1)
if res.IsOK() {
Exit(Fmt("expected bad transaction"))
}
//Test equal fees
CSW(2, 2)
if res.IsErr() {
Exit(Fmt("Failed: %v", res.Error()))
}
//Test more send coins than fees
CSW(2, 3)
if res.IsErr() {
Exit(Fmt("Failed: %v", res.Error()))
}
}

View File

@ -10,8 +10,6 @@ import (
// If the tx is invalid, a TMSP error will be returned.
func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc events.Fireable) abci.Result {
// TODO: do something with fees
fees := types.Coins{}
chainID := state.GetChainID()
// Exec tx
@ -46,10 +44,9 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
return res.PrependLog("in validateInputsAdvanced()")
}
outTotal := sumOutputs(tx.Outputs)
if !inTotal.IsEqual(outTotal.Plus(types.Coins{{"", tx.Fee}})) {
if !inTotal.IsEqual(outTotal.Plus(types.Coins{tx.Fee})) {
return abci.ErrBaseInvalidOutput.AppendLog("Input total != output total + fees")
}
fees = fees.Plus(types.Coins{{"", tx.Fee}})
// TODO: Fee validation for SendTx
@ -96,7 +93,7 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
log.Info(Fmt("validateInputAdvanced failed on %X: %v", tx.Input.Address, res))
return res.PrependLog("in validateInputAdvanced()")
}
if !tx.Input.Coins.IsGTE(types.Coins{{"", tx.Fee}}) {
if !tx.Input.Coins.IsGTE(types.Coins{tx.Fee}) {
log.Info(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
return abci.ErrBaseInsufficientFunds
}
@ -109,7 +106,7 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
}
// Good!
coins := tx.Input.Coins.Minus(types.Coins{{"", tx.Fee}})
coins := tx.Input.Coins.Minus(types.Coins{tx.Fee})
inAcc.Sequence += 1
inAcc.Balance = inAcc.Balance.Minus(tx.Input.Coins)
@ -120,13 +117,12 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
}
// Create inAcc checkpoint
inAccDeducted := inAcc.Copy()
inAccCopy := inAcc.Copy()
// Run the tx.
// XXX cache := types.NewStateCache(state)
cache := state.CacheWrap()
cache.SetAccount(tx.Input.Address, inAcc)
ctx := types.NewCallContext(tx.Input.Address, coins)
ctx := types.NewCallContext(tx.Input.Address, inAcc, coins)
res = plugin.RunTx(cache, ctx, tx.Data)
if res.IsOK() {
cache.CacheSync()
@ -145,10 +141,10 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
} else {
log.Info("AppTx failed", "error", res)
// Just return the coins and return.
inAccDeducted.Balance = inAccDeducted.Balance.Plus(coins)
inAccCopy.Balance = inAccCopy.Balance.Plus(coins)
// But take the gas
// TODO
state.SetAccount(tx.Input.Address, inAccDeducted)
state.SetAccount(tx.Input.Address, inAccCopy)
}
return res

View File

@ -5,9 +5,9 @@ import (
"time"
"github.com/gorilla/websocket"
cmn "github.com/tendermint/basecoin/common"
"github.com/tendermint/basecoin/testutils"
"github.com/tendermint/basecoin/types"
. "github.com/tendermint/go-common"
cmn "github.com/tendermint/go-common"
"github.com/tendermint/go-rpc/client"
"github.com/tendermint/go-rpc/types"
"github.com/tendermint/go-wire"
@ -21,7 +21,7 @@ func main() {
_, err := ws.Start()
if err != nil {
Exit(err.Error())
cmn.Exit(err.Error())
}
var counter = 0
@ -32,15 +32,15 @@ func main() {
if !ok {
break
}
fmt.Println(counter, "res:", Blue(string(res)))
fmt.Println(counter, "res:", cmn.Blue(string(res)))
}
}()
// Get the root account
root := cmn.PrivAccountFromSecret("test")
root := testutils.PrivAccountFromSecret("test")
sequence := int(0)
// Make a bunch of PrivAccounts
privAccounts := cmn.RandAccounts(1000, 1000000, 0)
privAccounts := testutils.RandAccounts(1000, 1000000, 0)
privAccountSequences := make(map[string]int)
// Send coins to each account
@ -72,12 +72,12 @@ func main() {
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", Arr(txBytes))
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes))
reqBytes := wire.JSONBytes(request)
//fmt.Print(".")
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
if err != nil {
Exit("writing websocket request: " + err.Error())
cmn.Exit("writing websocket request: " + err.Error())
}
}
@ -86,8 +86,8 @@ func main() {
counter += 1
time.Sleep(time.Millisecond * 10)
randA := RandInt() % len(privAccounts)
randB := RandInt() % len(privAccounts)
randA := cmn.RandInt() % len(privAccounts)
randB := cmn.RandInt() % len(privAccounts)
if randA == randB {
continue
}
@ -122,12 +122,12 @@ func main() {
// Write request
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", Arr(txBytes))
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes))
reqBytes := wire.JSONBytes(request)
//fmt.Print(".")
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
if err != nil {
Exit("writing websocket request: " + err.Error())
cmn.Exit("writing websocket request: " + err.Error())
}
}

View File

@ -1,5 +1,5 @@
//functions used in testing throughout
package common
// Functions used in testing throughout
package testutils
import (
"github.com/tendermint/basecoin/types"
@ -45,17 +45,3 @@ func RandAccounts(num int, minAmount int64, maxAmount int64) []types.PrivAccount
return privAccs
}
//make input term for the AppTx or SendTx Types
func MakeInput(pubKey crypto.PubKey, coins types.Coins, sequence int) types.TxInput {
input := types.TxInput{
Address: pubKey.Address(),
PubKey: pubKey,
Coins: coins,
Sequence: sequence,
}
if sequence > 1 {
input.PubKey = nil
}
return input
}

View File

@ -128,3 +128,15 @@ func (coins Coins) IsPositive() bool {
}
return true
}
func (coins Coins) IsNonnegative() bool {
if len(coins) == 0 {
return true
}
for _, coinAmount := range coins {
if coinAmount.Amount < 0 {
return false
}
}
return true
}

View File

@ -1,10 +1,12 @@
package types
import (
"fmt"
abci "github.com/tendermint/abci/types"
)
type Plugin interface {
Name() string
SetOption(store KVStore, key string, value string) (log string)
RunTx(store KVStore, ctx CallContext, txBytes []byte) (res abci.Result)
InitChain(store KVStore, vals []*abci.Validator)
@ -12,22 +14,21 @@ type Plugin interface {
EndBlock(store KVStore, height uint64) []*abci.Validator
}
type NamedPlugin struct {
Name string
Plugin
}
//----------------------------------------
// CallContext.Caller's coins have been deducted by CallContext.Coins
// Caller's Sequence has been incremented.
type CallContext struct {
Caller []byte
Coins Coins
CallerAddress []byte
CallerAccount *Account
Coins Coins
}
func NewCallContext(caller []byte, coins Coins) CallContext {
func NewCallContext(callerAddress []byte, callerAccount *Account, coins Coins) CallContext {
return CallContext{
Caller: caller,
Coins: coins,
CallerAddress: callerAddress,
CallerAccount: callerAccount,
Coins: coins,
}
}
@ -35,7 +36,7 @@ func NewCallContext(caller []byte, coins Coins) CallContext {
type Plugins struct {
byName map[string]Plugin
plist []NamedPlugin
plist []Plugin
}
func NewPlugins() *Plugins {
@ -44,18 +45,22 @@ func NewPlugins() *Plugins {
}
}
func (pgz *Plugins) RegisterPlugin(name string, plugin 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, NamedPlugin{
Name: name,
Plugin: plugin,
})
pgz.plist = append(pgz.plist, plugin)
}
func (pgz *Plugins) GetByName(name string) Plugin {
return pgz.byName[name]
}
func (pgz *Plugins) GetList() []NamedPlugin {
func (pgz *Plugins) GetList() []Plugin {
return pgz.plist
}

View File

@ -75,6 +75,19 @@ 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(),
PubKey: pubKey,
Coins: coins,
Sequence: sequence,
}
if sequence > 1 {
input.PubKey = nil
}
return input
}
//-----------------------------------------------------------------------------
type TxOutput struct {
@ -102,8 +115,8 @@ func (txOut TxOutput) String() string {
//-----------------------------------------------------------------------------
type SendTx struct {
Fee int64 `json:"fee"` // Fee
Gas int64 `json:"gas"` // Gas
Fee Coin `json:"fee"` // Fee
Inputs []TxInput `json:"inputs"`
Outputs []TxOutput `json:"outputs"`
}
@ -133,14 +146,14 @@ func (tx *SendTx) SetSignature(addr []byte, sig crypto.Signature) bool {
}
func (tx *SendTx) String() string {
return Fmt("SendTx{%v/%v %v->%v}", tx.Fee, tx.Gas, tx.Inputs, tx.Outputs)
return Fmt("SendTx{%v/%v %v->%v}", tx.Gas, tx.Fee, tx.Inputs, tx.Outputs)
}
//-----------------------------------------------------------------------------
type AppTx struct {
Fee int64 `json:"fee"` // Fee
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 []byte `json:"data"`
@ -161,7 +174,7 @@ func (tx *AppTx) SetSignature(sig crypto.Signature) bool {
}
func (tx *AppTx) String() string {
return Fmt("AppTx{%v/%v %v %v %X}", tx.Fee, tx.Gas, tx.Name, tx.Input, tx.Data)
return Fmt("AppTx{%v/%v %v %v %X}", tx.Gas, tx.Fee, tx.Name, tx.Input, tx.Data)
}
//-----------------------------------------------------------------------------

View File

@ -10,8 +10,8 @@ var chainID string = "test_chain"
func TestSendTxSignable(t *testing.T) {
sendTx := &SendTx{
Fee: 111,
Gas: 222,
Fee: Coin{"", 111},
Inputs: []TxInput{
TxInput{
Address: []byte("input1"),
@ -37,7 +37,7 @@ func TestSendTxSignable(t *testing.T) {
}
signBytes := sendTx.SignBytes(chainID)
signBytesHex := Fmt("%X", signBytes)
expected := "010A746573745F636861696E01000000000000006F00000000000000DE01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC"
expected := "010A746573745F636861696E0100000000000000DE00000000000000006F01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC"
if signBytesHex != expected {
t.Errorf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)
}
@ -45,8 +45,8 @@ func TestSendTxSignable(t *testing.T) {
func TestAppTxSignable(t *testing.T) {
callTx := &AppTx{
Fee: 111,
Gas: 222,
Fee: Coin{"", 111},
Name: "X",
Input: TxInput{
Address: []byte("input1"),
@ -57,7 +57,7 @@ func TestAppTxSignable(t *testing.T) {
}
signBytes := callTx.SignBytes(chainID)
signBytesHex := Fmt("%X", signBytes)
expected := "010A746573745F636861696E01000000000000006F00000000000000DE0101580106696E70757431010100000000000000303903010932000001056461746131"
expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131"
if signBytesHex != expected {
t.Errorf("Got unexpected sign string for AppTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)
}