Use new go-crypto S structs to get full go-data support

This commit is contained in:
Ethan Frey 2017-02-23 17:04:03 +01:00
parent fe81f87a13
commit c1fa8cb0d2
11 changed files with 94 additions and 65 deletions

View File

@ -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)))

4
glide.lock generated
View File

@ -65,7 +65,9 @@ imports:
- name: github.com/tendermint/go-config
version: e64b424499acd0eb9856b88e10c0dff41628c0d6
- name: github.com/tendermint/go-crypto
version: 4b11d62bdb324027ea01554e5767b71174680ba0
version: b6a2c5949f7ea1d064cbb9dc638eb0a3dca9af34
- name: github.com/tendermint/go-data
version: 35a95d275fa845b635e1208c3dd65b19c4eda811
- name: github.com/tendermint/go-db
version: 2645626c33d8702739e52a61a55d705c2dfe4530
- name: github.com/tendermint/go-events

View File

@ -8,6 +8,7 @@ import (
"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"
)
@ -47,8 +48,8 @@ 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
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

View File

@ -31,7 +31,7 @@ func genGenesisDoc(chainID string, numVals int) (*tm.GenesisDoc, []types.PrivAcc
name := cmn.Fmt("%v_val_%v", chainID, i)
privAcc := testutils.PrivAccountFromSecret(name)
genDoc.Validators = append(genDoc.Validators, tm.GenesisValidator{
PubKey: privAcc.Account.PubKey,
PubKey: privAcc.PubKey.PubKey,
Amount: 1,
Name: name,
})

View File

@ -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

View File

@ -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

View File

@ -8,6 +8,7 @@ import (
"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"
@ -66,8 +67,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 +117,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

View File

@ -7,6 +7,7 @@ import (
"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"
)
@ -44,12 +45,12 @@ 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}))
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() {
@ -96,8 +97,8 @@ 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
@ -133,11 +134,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,8 +146,8 @@ 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

View File

@ -12,9 +12,9 @@ import (
func PrivAccountFromSecret(secret string) types.PrivAccount {
privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret))
privAccount := types.PrivAccount{
PrivKey: privKey,
PrivKeyS: crypto.PrivKeyS{privKey},
Account: types.Account{
PubKey: privKey.PubKey(),
PubKey: crypto.PubKeyS{privKey.PubKey()},
Sequence: 0,
},
}
@ -32,9 +32,9 @@ func RandAccounts(num int, minAmount int64, maxAmount int64) []types.PrivAccount
}
privKey := crypto.GenPrivKeyEd25519()
pubKey := privKey.PubKey()
pubKey := crypto.PubKeyS{privKey.PubKey()}
privAccs[i] = types.PrivAccount{
PrivKey: privKey,
PrivKeyS: crypto.PrivKeyS{privKey},
Account: types.Account{
PubKey: pubKey,
Sequence: 0,

View File

@ -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
}

View File

@ -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,11 +153,11 @@ 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
}
@ -138,7 +165,7 @@ func (tx *SendTx) SignBytes(chainID string) []byte {
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
tx.Inputs[i].Signature.Signature = sig
return true
}
}
@ -152,24 +179,24 @@ 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
tx.Input.Signature.Signature = sig
return true
}