commit
ce5ecc7db4
2
Makefile
2
Makefile
|
@ -11,7 +11,7 @@ install:
|
|||
go install github.com/tendermint/basecoin/cmd/...
|
||||
|
||||
test:
|
||||
go test --race `${NOVENDOR}`
|
||||
go test `${NOVENDOR}`
|
||||
#go run tests/tendermint/*.go
|
||||
|
||||
get_deps:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
|
@ -68,13 +69,12 @@ func (app *Basecoin) SetOption(key string, value string) string {
|
|||
app.state.SetChainID(value)
|
||||
return "Success"
|
||||
case "account":
|
||||
var err error
|
||||
var acc *types.Account
|
||||
wire.ReadJSONPtr(&acc, []byte(value), &err)
|
||||
var acc types.Account
|
||||
err := json.Unmarshal([]byte(value), &acc)
|
||||
if err != nil {
|
||||
return "Error decoding acc message: " + err.Error()
|
||||
}
|
||||
app.state.SetAccount(acc.PubKey.Address(), acc)
|
||||
app.state.SetAccount(acc.PubKey.Address(), &acc)
|
||||
log.Info("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
|
||||
return "Success"
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package app
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
|
@ -15,9 +13,7 @@ func (app *Basecoin) LoadGenesis(path string) error {
|
|||
return err
|
||||
}
|
||||
for _, kv := range kvz {
|
||||
log := app.SetOption(kv.Key, kv.Value)
|
||||
// TODO: remove debug output
|
||||
fmt.Printf("Set %v=%v. Log: %v\n", kv.Key, kv.Value, log)
|
||||
app.SetOption(kv.Key, kv.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -28,7 +24,7 @@ type keyValue struct {
|
|||
}
|
||||
|
||||
func loadGenesis(filePath string) (kvz []keyValue, err error) {
|
||||
kvz_ := []interface{}{}
|
||||
kvz_ := []json.RawMessage{}
|
||||
bytes, err := cmn.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "loading genesis file")
|
||||
|
@ -40,24 +36,21 @@ func loadGenesis(filePath string) (kvz []keyValue, err error) {
|
|||
if len(kvz_)%2 != 0 {
|
||||
return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]")
|
||||
}
|
||||
|
||||
for i := 0; i < len(kvz_); i += 2 {
|
||||
keyIfc := kvz_[i]
|
||||
valueIfc := kvz_[i+1]
|
||||
var key, value string
|
||||
key, ok := keyIfc.(string)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("genesis had invalid key %v of type %v", keyIfc, reflect.TypeOf(keyIfc))
|
||||
kv := keyValue{}
|
||||
rawK := []byte(kvz_[i])
|
||||
err := json.Unmarshal(rawK, &(kv.Key))
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("Non-string key: %s", string(rawK))
|
||||
}
|
||||
if value_, ok := valueIfc.(string); ok {
|
||||
value = value_
|
||||
} else {
|
||||
valueBytes, err := json.Marshal(valueIfc)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("genesis had invalid value %v: %v", value_, err.Error())
|
||||
}
|
||||
value = string(valueBytes)
|
||||
// convert value to string if possible (otherwise raw json)
|
||||
rawV := kvz_[i+1]
|
||||
err = json.Unmarshal(rawV, &(kv.Value))
|
||||
if err != nil {
|
||||
kv.Value = string(rawV)
|
||||
}
|
||||
kvz = append(kvz, keyValue{key, value})
|
||||
kvz = append(kvz, kv)
|
||||
}
|
||||
return kvz, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/go-crypto"
|
||||
eyescli "github.com/tendermint/merkleeyes/client"
|
||||
)
|
||||
|
||||
func TestLoadGenesis(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
eyesCli := eyescli.NewLocalClient("", 0)
|
||||
app := NewBasecoin(eyesCli)
|
||||
err := app.LoadGenesis("./testdata/genesis.json")
|
||||
require.Nil(err, "%+v", err)
|
||||
|
||||
// check the chain id
|
||||
assert.Equal("foo_bar_chain", app.GetState().GetChainID())
|
||||
|
||||
// and check the account info - previously calculated values
|
||||
addr, _ := hex.DecodeString("eb98e0688217cfdeb70eddf4b33cdcc37fc53197")
|
||||
pkbyte, _ := hex.DecodeString("6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2")
|
||||
|
||||
acct := app.GetState().GetAccount(addr)
|
||||
require.NotNil(acct)
|
||||
|
||||
// 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)
|
||||
|
||||
// and public key is parsed properly
|
||||
apk := acct.PubKey.PubKey
|
||||
require.NotNil(apk)
|
||||
epk, ok := apk.(crypto.PubKeyEd25519)
|
||||
if assert.True(ok) {
|
||||
assert.EqualValues(pkbyte, epk[:])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
"base/chainID", "foo_bar_chain",
|
||||
"base/account", {
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "blank",
|
||||
"amount": 12345
|
||||
},
|
||||
{
|
||||
"denom": "ETH",
|
||||
"amount": 654321
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/tendermint/basecoin/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
cmn "github.com/tendermint/go-common"
|
||||
client "github.com/tendermint/go-rpc/client"
|
||||
|
@ -113,7 +114,7 @@ func cmdSendTx(c *cli.Context) error {
|
|||
|
||||
// sign that puppy
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
tx.Inputs[0].Signature = privKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{privKey.Sign(signBytes)}
|
||||
|
||||
fmt.Println("Signed SendTx:")
|
||||
fmt.Println(string(wire.JSONBytes(tx)))
|
||||
|
@ -169,7 +170,7 @@ func AppTx(c *cli.Context, name string, data []byte) error {
|
|||
Data: data,
|
||||
}
|
||||
|
||||
tx.Input.Signature = privKey.Sign(tx.SignBytes(chainID))
|
||||
tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainID))}
|
||||
|
||||
fmt.Println("Signed AppTx:")
|
||||
fmt.Println(string(wire.JSONBytes(tx)))
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
[
|
||||
"base/chainID", "test_chain_id",
|
||||
"base/account", {
|
||||
"pub_key": [1, "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"],
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
[
|
||||
"base/chainID", "test_chain_1",
|
||||
"base/account", {
|
||||
"pub_key": [1, "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"],
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
[
|
||||
"base/chainID", "test_chain_2",
|
||||
"base/account", {
|
||||
"pub_key": [1, "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"],
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
||||
},
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 9007199254740992
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -65,7 +65,9 @@ imports:
|
|||
- name: github.com/tendermint/go-config
|
||||
version: e64b424499acd0eb9856b88e10c0dff41628c0d6
|
||||
- name: github.com/tendermint/go-crypto
|
||||
version: 4b11d62bdb324027ea01554e5767b71174680ba0
|
||||
version: 562b4cc9ef0d20217f6e95679f9e83cb7bc98b17
|
||||
- name: github.com/tendermint/go-data
|
||||
version: f199ef165cd5a50d569b179201702c5ec8899013
|
||||
- name: github.com/tendermint/go-db
|
||||
version: 2645626c33d8702739e52a61a55d705c2dfe4530
|
||||
- name: github.com/tendermint/go-events
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package counter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/basecoin/app"
|
||||
"github.com/tendermint/basecoin/testutils"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
eyescli "github.com/tendermint/merkleeyes/client"
|
||||
)
|
||||
|
@ -19,19 +21,21 @@ func TestCounterPlugin(t *testing.T) {
|
|||
chainID := "test_chain_id"
|
||||
bcApp := app.NewBasecoin(eyesCli)
|
||||
bcApp.SetOption("base/chainID", chainID)
|
||||
t.Log(bcApp.Info())
|
||||
// t.Log(bcApp.Info())
|
||||
|
||||
// Add Counter plugin
|
||||
counterPlugin := New()
|
||||
bcApp.RegisterPlugin(counterPlugin)
|
||||
|
||||
// Account initialization
|
||||
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
|
||||
test1PrivAcc := types.PrivAccountFromSecret("test1")
|
||||
|
||||
// Seed Basecoin with account
|
||||
test1Acc := test1PrivAcc.Account
|
||||
test1Acc.Balance = types.Coins{{"", 1000}, {"gold", 1000}}
|
||||
bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc)))
|
||||
accOpt, err := json.Marshal(test1Acc)
|
||||
require.Nil(t, err)
|
||||
bcApp.SetOption("base/account", string(accOpt))
|
||||
|
||||
// Deliver a CounterTx
|
||||
DeliverCounterTx := func(gas int64, fee types.Coin, inputCoins types.Coins, inputSequence int, appFee types.Coins) abci.Result {
|
||||
|
@ -46,10 +50,10 @@ func TestCounterPlugin(t *testing.T) {
|
|||
|
||||
// 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}))
|
||||
// t.Logf("Sign bytes: %X\n", signBytes)
|
||||
sig := test1PrivAcc.Sign(signBytes)
|
||||
tx.Input.Signature = crypto.SignatureS{sig}
|
||||
// t.Logf("Signed TX bytes: %X\n", wire.BinaryBytes(struct{ types.Tx }{tx}))
|
||||
|
||||
// Write request
|
||||
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/basecoin/testutils"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
@ -29,9 +28,9 @@ func genGenesisDoc(chainID string, numVals int) (*tm.GenesisDoc, []types.PrivAcc
|
|||
|
||||
for i := 0; i < numVals; i++ {
|
||||
name := cmn.Fmt("%v_val_%v", chainID, i)
|
||||
privAcc := testutils.PrivAccountFromSecret(name)
|
||||
privAcc := types.PrivAccountFromSecret(name)
|
||||
genDoc.Validators = append(genDoc.Validators, tm.GenesisValidator{
|
||||
PubKey: privAcc.Account.PubKey,
|
||||
PubKey: privAcc.PubKey.PubKey,
|
||||
Amount: 1,
|
||||
Name: name,
|
||||
})
|
||||
|
|
|
@ -87,7 +87,7 @@ func ExecTx(state *State, pgz *types.Plugins, tx types.Tx, isCheckTx bool, evc e
|
|||
if inAcc == nil {
|
||||
return abci.ErrBaseUnknownAddress
|
||||
}
|
||||
if tx.Input.PubKey != nil {
|
||||
if !tx.Input.PubKey.Empty() {
|
||||
inAcc.PubKey = tx.Input.PubKey
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ func getInputs(state types.AccountGetter, ins []types.TxInput) (map[string]*type
|
|||
return nil, abci.ErrBaseUnknownAddress
|
||||
}
|
||||
|
||||
if in.PubKey != nil {
|
||||
if !in.PubKey.Empty() {
|
||||
acc.PubKey = in.PubKey
|
||||
}
|
||||
accounts[string(in.Address)] = acc
|
||||
|
@ -197,10 +197,8 @@ func getOrMakeOutputs(state types.AccountGetter, accounts map[string]*types.Acco
|
|||
acc := state.GetAccount(out.Address)
|
||||
// output account may be nil (new)
|
||||
if acc == nil {
|
||||
acc = &types.Account{
|
||||
PubKey: nil,
|
||||
Sequence: 0,
|
||||
}
|
||||
// zero value is valid, empty account
|
||||
acc = &types.Account{}
|
||||
}
|
||||
accounts[string(out.Address)] = acc
|
||||
}
|
||||
|
@ -246,7 +244,7 @@ func validateInputAdvanced(acc *types.Account, signBytes []byte, in types.TxInpu
|
|||
return abci.ErrBaseInsufficientFunds.AppendLog(cmn.Fmt("balance is %v, tried to send %v", balance, in.Coins))
|
||||
}
|
||||
// Check signatures
|
||||
if !acc.PubKey.VerifyBytes(signBytes, in.Signature) {
|
||||
if !acc.PubKey.VerifyBytes(signBytes, in.Signature.Signature) {
|
||||
return abci.ErrBaseInvalidSignature.AppendLog(cmn.Fmt("SignBytes: %X", signBytes))
|
||||
}
|
||||
return abci.OK
|
||||
|
|
|
@ -22,9 +22,7 @@ func TestState(t *testing.T) {
|
|||
dumAddr := []byte("dummyAddress")
|
||||
|
||||
acc := &types.Account{
|
||||
PubKey: nil,
|
||||
Sequence: 1,
|
||||
Balance: nil,
|
||||
}
|
||||
|
||||
//reset the store/state/cache
|
||||
|
|
|
@ -5,9 +5,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/tendermint/basecoin/testutils"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-rpc/client"
|
||||
"github.com/tendermint/go-rpc/types"
|
||||
"github.com/tendermint/go-wire"
|
||||
|
@ -37,10 +37,10 @@ func main() {
|
|||
}()
|
||||
|
||||
// Get the root account
|
||||
root := testutils.PrivAccountFromSecret("test")
|
||||
root := types.PrivAccountFromSecret("test")
|
||||
sequence := int(0)
|
||||
// Make a bunch of PrivAccounts
|
||||
privAccounts := testutils.RandAccounts(1000, 1000000, 0)
|
||||
privAccounts := types.RandAccounts(1000, 1000000, 0)
|
||||
privAccountSequences := make(map[string]int)
|
||||
|
||||
// Send coins to each account
|
||||
|
@ -66,8 +66,8 @@ func main() {
|
|||
|
||||
// Sign request
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
sig := root.PrivKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = sig
|
||||
sig := root.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{sig}
|
||||
//fmt.Println("tx:", tx)
|
||||
|
||||
// Write request
|
||||
|
@ -116,8 +116,8 @@ func main() {
|
|||
|
||||
// Sign request
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
sig := privAccountA.PrivKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = sig
|
||||
sig := privAccountA.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{sig}
|
||||
//fmt.Println("tx:", tx)
|
||||
|
||||
// Write request
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package tmsp_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/basecoin/app"
|
||||
"github.com/tendermint/basecoin/testutils"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
eyescli "github.com/tendermint/merkleeyes/client"
|
||||
)
|
||||
|
@ -16,15 +19,17 @@ func TestSendTx(t *testing.T) {
|
|||
chainID := "test_chain_id"
|
||||
bcApp := app.NewBasecoin(eyesCli)
|
||||
bcApp.SetOption("base/chainID", chainID)
|
||||
t.Log(bcApp.Info())
|
||||
// t.Log(bcApp.Info())
|
||||
|
||||
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
|
||||
test2PrivAcc := testutils.PrivAccountFromSecret("test2")
|
||||
test1PrivAcc := types.PrivAccountFromSecret("test1")
|
||||
test2PrivAcc := types.PrivAccountFromSecret("test2")
|
||||
|
||||
// Seed Basecoin with account
|
||||
test1Acc := test1PrivAcc.Account
|
||||
test1Acc.Balance = types.Coins{{"", 1000}}
|
||||
t.Log(bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc))))
|
||||
accOpt, err := json.Marshal(test1Acc)
|
||||
require.Nil(t, err)
|
||||
bcApp.SetOption("base/account", string(accOpt))
|
||||
|
||||
// Construct a SendTx signature
|
||||
tx := &types.SendTx{
|
||||
|
@ -43,18 +48,16 @@ func TestSendTx(t *testing.T) {
|
|||
|
||||
// Sign request
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
t.Log("Sign bytes: %X\n", signBytes)
|
||||
sig := test1PrivAcc.PrivKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = sig
|
||||
t.Log("Signed TX bytes: %X\n", wire.BinaryBytes(struct{ types.Tx }{tx}))
|
||||
// t.Log("Sign bytes: %X\n", signBytes)
|
||||
sig := test1PrivAcc.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{sig}
|
||||
// t.Log("Signed TX bytes: %X\n", wire.BinaryBytes(types.TxS{tx}))
|
||||
|
||||
// Write request
|
||||
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
|
||||
txBytes := wire.BinaryBytes(types.TxS{tx})
|
||||
res := bcApp.DeliverTx(txBytes)
|
||||
t.Log(res)
|
||||
if res.IsErr() {
|
||||
t.Errorf("Failed: %v", res.Error())
|
||||
}
|
||||
// t.Log(res)
|
||||
assert.False(t, res.IsErr(), "Failed: %v", res.Error())
|
||||
}
|
||||
|
||||
func TestSequence(t *testing.T) {
|
||||
|
@ -62,17 +65,19 @@ func TestSequence(t *testing.T) {
|
|||
chainID := "test_chain_id"
|
||||
bcApp := app.NewBasecoin(eyesCli)
|
||||
bcApp.SetOption("base/chainID", chainID)
|
||||
t.Log(bcApp.Info())
|
||||
// t.Log(bcApp.Info())
|
||||
|
||||
// Get the test account
|
||||
test1PrivAcc := testutils.PrivAccountFromSecret("test1")
|
||||
test1PrivAcc := types.PrivAccountFromSecret("test1")
|
||||
test1Acc := test1PrivAcc.Account
|
||||
test1Acc.Balance = types.Coins{{"", 1 << 53}}
|
||||
t.Log(bcApp.SetOption("base/account", string(wire.JSONBytes(test1Acc))))
|
||||
accOpt, err := json.Marshal(test1Acc)
|
||||
require.Nil(t, err)
|
||||
bcApp.SetOption("base/account", string(accOpt))
|
||||
|
||||
sequence := int(1)
|
||||
// Make a bunch of PrivAccounts
|
||||
privAccounts := testutils.RandAccounts(1000, 1000000, 0)
|
||||
privAccounts := types.RandAccounts(1000, 1000000, 0)
|
||||
privAccountSequences := make(map[string]int)
|
||||
// Send coins to each account
|
||||
|
||||
|
@ -96,23 +101,18 @@ func TestSequence(t *testing.T) {
|
|||
|
||||
// Sign request
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
sig := test1PrivAcc.PrivKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = sig
|
||||
sig := test1PrivAcc.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{sig}
|
||||
// t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address)
|
||||
|
||||
// Write request
|
||||
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
|
||||
res := bcApp.DeliverTx(txBytes)
|
||||
if res.IsErr() {
|
||||
t.Errorf("DeliverTx error: " + res.Error())
|
||||
}
|
||||
|
||||
assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error())
|
||||
}
|
||||
|
||||
res := bcApp.Commit()
|
||||
if res.IsErr() {
|
||||
t.Errorf("Failed Commit: %v", res.Error())
|
||||
}
|
||||
assert.False(t, res.IsErr(), "Failed Commit: %v", res.Error())
|
||||
|
||||
t.Log("-------------------- RANDOM SENDS --------------------")
|
||||
|
||||
|
@ -133,11 +133,11 @@ func TestSequence(t *testing.T) {
|
|||
Gas: 2,
|
||||
Fee: types.Coin{"", 2},
|
||||
Inputs: []types.TxInput{
|
||||
types.NewTxInput(privAccountA.Account.PubKey, types.Coins{{"", 3}}, privAccountASequence+1),
|
||||
types.NewTxInput(privAccountA.PubKey, types.Coins{{"", 3}}, privAccountASequence+1),
|
||||
},
|
||||
Outputs: []types.TxOutput{
|
||||
types.TxOutput{
|
||||
Address: privAccountB.Account.PubKey.Address(),
|
||||
Address: privAccountB.PubKey.Address(),
|
||||
Coins: types.Coins{{"", 1}},
|
||||
},
|
||||
},
|
||||
|
@ -145,15 +145,13 @@ func TestSequence(t *testing.T) {
|
|||
|
||||
// Sign request
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
sig := privAccountA.PrivKey.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = sig
|
||||
sig := privAccountA.Sign(signBytes)
|
||||
tx.Inputs[0].Signature = crypto.SignatureS{sig}
|
||||
// t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address)
|
||||
|
||||
// Write request
|
||||
txBytes := wire.BinaryBytes(struct{ types.Tx }{tx})
|
||||
res := bcApp.DeliverTx(txBytes)
|
||||
if res.IsErr() {
|
||||
t.Errorf("DeliverTx error: " + res.Error())
|
||||
}
|
||||
assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
// Functions used in testing throughout
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"github.com/tendermint/basecoin/types"
|
||||
. "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// Creates a PrivAccount from secret.
|
||||
// The amount is not set.
|
||||
func PrivAccountFromSecret(secret string) types.PrivAccount {
|
||||
privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret))
|
||||
privAccount := types.PrivAccount{
|
||||
PrivKey: privKey,
|
||||
Account: types.Account{
|
||||
PubKey: privKey.PubKey(),
|
||||
Sequence: 0,
|
||||
},
|
||||
}
|
||||
return privAccount
|
||||
}
|
||||
|
||||
// Make `num` random accounts
|
||||
func RandAccounts(num int, minAmount int64, maxAmount int64) []types.PrivAccount {
|
||||
privAccs := make([]types.PrivAccount, num)
|
||||
for i := 0; i < num; i++ {
|
||||
|
||||
balance := minAmount
|
||||
if maxAmount > minAmount {
|
||||
balance += RandInt64() % (maxAmount - minAmount)
|
||||
}
|
||||
|
||||
privKey := crypto.GenPrivKeyEd25519()
|
||||
pubKey := privKey.PubKey()
|
||||
privAccs[i] = types.PrivAccount{
|
||||
PrivKey: privKey,
|
||||
Account: types.Account{
|
||||
PubKey: pubKey,
|
||||
Sequence: 0,
|
||||
Balance: types.Coins{types.Coin{"", balance}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return privAccs
|
||||
}
|
|
@ -7,9 +7,9 @@ import (
|
|||
)
|
||||
|
||||
type Account struct {
|
||||
PubKey crypto.PubKey `json:"pub_key"` // May be nil, if not known.
|
||||
Sequence int `json:"sequence"`
|
||||
Balance Coins `json:"coins"`
|
||||
PubKey crypto.PubKeyS `json:"pub_key"` // May be nil, if not known.
|
||||
Sequence int `json:"sequence"`
|
||||
Balance Coins `json:"coins"`
|
||||
}
|
||||
|
||||
func (acc *Account) Copy() *Account {
|
||||
|
@ -31,7 +31,7 @@ func (acc *Account) String() string {
|
|||
//----------------------------------------
|
||||
|
||||
type PrivAccount struct {
|
||||
crypto.PrivKey
|
||||
crypto.PrivKeyS
|
||||
Account
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,9 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAccount(t *testing.T) {
|
||||
func TestNilAccount(t *testing.T) {
|
||||
|
||||
acc := Account{
|
||||
PubKey: nil,
|
||||
Sequence: 0,
|
||||
Balance: nil,
|
||||
}
|
||||
acc := Account{}
|
||||
|
||||
//test Copy
|
||||
accCopy := acc.Copy()
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package types
|
||||
|
||||
// Helper functions for testing
|
||||
|
||||
import (
|
||||
cmn "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// Creates a PrivAccount from secret.
|
||||
// The amount is not set.
|
||||
func PrivAccountFromSecret(secret string) PrivAccount {
|
||||
privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret))
|
||||
privAccount := PrivAccount{
|
||||
PrivKeyS: crypto.PrivKeyS{privKey},
|
||||
Account: Account{
|
||||
PubKey: crypto.PubKeyS{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++ {
|
||||
|
||||
balance := minAmount
|
||||
if maxAmount > minAmount {
|
||||
balance += cmn.RandInt64() % (maxAmount - minAmount)
|
||||
}
|
||||
|
||||
privKey := crypto.GenPrivKeyEd25519()
|
||||
pubKey := crypto.PubKeyS{privKey.PubKey()}
|
||||
privAccs[i] = PrivAccount{
|
||||
PrivKeyS: crypto.PrivKeyS{privKey},
|
||||
Account: Account{
|
||||
PubKey: pubKey,
|
||||
Balance: Coins{Coin{"", balance}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return privAccs
|
||||
}
|
91
types/tx.go
91
types/tx.go
|
@ -7,6 +7,7 @@ import (
|
|||
abci "github.com/tendermint/abci/types"
|
||||
. "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-data"
|
||||
"github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
|
@ -17,7 +18,6 @@ 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
|
||||
|
@ -28,25 +28,47 @@ const (
|
|||
// Account transactions
|
||||
TxTypeSend = byte(0x01)
|
||||
TxTypeApp = byte(0x02)
|
||||
TxNameSend = "send"
|
||||
TxNameApp = "app"
|
||||
)
|
||||
|
||||
func (_ *SendTx) AssertIsTx() {}
|
||||
func (_ *AppTx) AssertIsTx() {}
|
||||
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ Tx }{},
|
||||
wire.ConcreteType{&SendTx{}, TxTypeSend},
|
||||
wire.ConcreteType{&AppTx{}, TxTypeApp},
|
||||
)
|
||||
var txMapper data.Mapper
|
||||
|
||||
// register both private key types with go-data (and thus go-wire)
|
||||
func init() {
|
||||
txMapper = data.NewMapper(TxS{}).
|
||||
RegisterInterface(&SendTx{}, TxNameSend, TxTypeSend).
|
||||
RegisterInterface(&AppTx{}, TxNameApp, TxTypeApp)
|
||||
}
|
||||
|
||||
// TxS add json serialization to Tx
|
||||
type TxS struct {
|
||||
Tx
|
||||
}
|
||||
|
||||
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 []byte `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
|
||||
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.SignatureS `json:"signature"` // Depends on the PubKey type and the whole Tx
|
||||
PubKey crypto.PubKeyS `json:"pub_key"` // Is present iff Sequence == 0
|
||||
}
|
||||
|
||||
func (txIn TxInput) ValidateBasic() abci.Result {
|
||||
|
@ -62,10 +84,10 @@ func (txIn TxInput) ValidateBasic() abci.Result {
|
|||
if txIn.Sequence <= 0 {
|
||||
return abci.ErrBaseInvalidInput.AppendLog("Sequence must be greater than 0")
|
||||
}
|
||||
if txIn.Sequence == 1 && txIn.PubKey == nil {
|
||||
if txIn.Sequence == 1 && txIn.PubKey.Empty() {
|
||||
return abci.ErrBaseInvalidInput.AppendLog("PubKey must be present when Sequence == 1")
|
||||
}
|
||||
if txIn.Sequence > 1 && txIn.PubKey != nil {
|
||||
if txIn.Sequence > 1 && !txIn.PubKey.Empty() {
|
||||
return abci.ErrBaseInvalidInput.AppendLog("PubKey must be nil when Sequence > 1")
|
||||
}
|
||||
return abci.OK
|
||||
|
@ -78,12 +100,17 @@ func (txIn TxInput) String() string {
|
|||
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
|
||||
if sequence == 1 {
|
||||
// safely wrap if needed
|
||||
// TODO: extract this as utility function?
|
||||
ps, ok := pubKey.(crypto.PubKeyS)
|
||||
if !ok {
|
||||
ps = crypto.PubKeyS{pubKey}
|
||||
}
|
||||
input.PubKey = ps
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
@ -91,8 +118,8 @@ func NewTxInput(pubKey crypto.PubKey, coins Coins, sequence int) TxInput {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
type TxOutput struct {
|
||||
Address []byte `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
Address data.Bytes `json:"address"` // Hash of the PubKey
|
||||
Coins Coins `json:"coins"` //
|
||||
}
|
||||
|
||||
func (txOut TxOutput) ValidateBasic() abci.Result {
|
||||
|
@ -126,19 +153,23 @@ func (tx *SendTx) SignBytes(chainID string) []byte {
|
|||
sigz := make([]crypto.Signature, len(tx.Inputs))
|
||||
for i, input := range tx.Inputs {
|
||||
sigz[i] = input.Signature
|
||||
tx.Inputs[i].Signature = nil
|
||||
tx.Inputs[i].Signature.Signature = nil
|
||||
}
|
||||
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
|
||||
for i := range tx.Inputs {
|
||||
tx.Inputs[i].Signature = sigz[i]
|
||||
tx.Inputs[i].Signature.Signature = sigz[i]
|
||||
}
|
||||
return signBytes
|
||||
}
|
||||
|
||||
func (tx *SendTx) SetSignature(addr []byte, sig crypto.Signature) bool {
|
||||
sigs, ok := sig.(crypto.SignatureS)
|
||||
if !ok {
|
||||
sigs = crypto.SignatureS{sig}
|
||||
}
|
||||
for i, input := range tx.Inputs {
|
||||
if bytes.Equal(input.Address, addr) {
|
||||
tx.Inputs[i].Signature = sig
|
||||
tx.Inputs[i].Signature = sigs
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -152,24 +183,28 @@ func (tx *SendTx) String() string {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
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 []byte `json:"data"`
|
||||
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 = nil
|
||||
tx.Input.Signature.Signature = nil
|
||||
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
|
||||
tx.Input.Signature = sig
|
||||
return signBytes
|
||||
}
|
||||
|
||||
func (tx *AppTx) SetSignature(sig crypto.Signature) bool {
|
||||
tx.Input.Signature = sig
|
||||
sigs, ok := sig.(crypto.SignatureS)
|
||||
if !ok {
|
||||
sigs = crypto.SignatureS{sig}
|
||||
}
|
||||
tx.Input.Signature = sigs
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ package types
|
|||
import (
|
||||
"testing"
|
||||
|
||||
cmn "github.com/tendermint/go-common"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
cmn "github.com/tendermint/go-common"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
data "github.com/tendermint/go-data"
|
||||
)
|
||||
|
||||
var chainID string = "test_chain"
|
||||
|
@ -62,5 +64,62 @@ func TestAppTxSignable(t *testing.T) {
|
|||
expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131"
|
||||
|
||||
assert.True(t, signBytesHex == expected,
|
||||
cmn.Fmt("Got unexpected sign string for AppTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex))
|
||||
cmn.Fmt("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex))
|
||||
}
|
||||
|
||||
func TestSendTxJSON(t *testing.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(t, err)
|
||||
// fmt.Println(string(js))
|
||||
txs := TxS{}
|
||||
err = data.FromJSON(js, &txs)
|
||||
require.Nil(t, err)
|
||||
tx2, ok := txs.Tx.(*SendTx)
|
||||
require.True(t, ok)
|
||||
|
||||
// make sure they are the same!
|
||||
signBytes := tx.SignBytes(chainID)
|
||||
signBytes2 := tx2.SignBytes(chainID)
|
||||
assert.Equal(t, signBytes, signBytes2)
|
||||
assert.Equal(t, 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(), crypto.SignatureS{sig})
|
||||
assert.Equal(t, tx, tx2)
|
||||
|
||||
// let's marshal / unmarshal this with signature
|
||||
js, err = data.ToJSON(TxS{tx})
|
||||
require.Nil(t, err)
|
||||
// fmt.Println(string(js))
|
||||
err = data.FromJSON(js, &txs)
|
||||
require.Nil(t, err)
|
||||
tx2, ok = txs.Tx.(*SendTx)
|
||||
require.True(t, ok)
|
||||
|
||||
// and make sure the sig is preserved
|
||||
assert.Equal(t, tx, tx2)
|
||||
assert.False(t, tx2.Inputs[0].Signature.Empty())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue