From c1fa8cb0d21d3bb424638a4e694b2a86f3b4fe36 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 17:04:03 +0100 Subject: [PATCH] Use new go-crypto S structs to get full go-data support --- cmd/commands/tx.go | 5 +- glide.lock | 4 +- plugins/counter/counter_test.go | 5 +- plugins/ibc/ibc_test.go | 2 +- state/execution.go | 12 ++--- state/state_test.go | 2 - tests/tendermint/main.go | 9 ++-- tests/tmsp/tmsp_test.go | 21 +++++---- testutils/testing.go | 8 ++-- types/account.go | 8 ++-- types/tx.go | 83 ++++++++++++++++++++++----------- 11 files changed, 94 insertions(+), 65 deletions(-) diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 68b0afa102..de1a923277 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -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))) diff --git a/glide.lock b/glide.lock index 3b315bbef6..ca1aad031b 100644 --- a/glide.lock +++ b/glide.lock @@ -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 diff --git a/plugins/counter/counter_test.go b/plugins/counter/counter_test.go index a4c4236230..e96cbc56b0 100644 --- a/plugins/counter/counter_test.go +++ b/plugins/counter/counter_test.go @@ -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 diff --git a/plugins/ibc/ibc_test.go b/plugins/ibc/ibc_test.go index 6bc3f0706e..51ee5f31f9 100644 --- a/plugins/ibc/ibc_test.go +++ b/plugins/ibc/ibc_test.go @@ -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, }) diff --git a/state/execution.go b/state/execution.go index b73cab4dc0..3452c399ab 100644 --- a/state/execution.go +++ b/state/execution.go @@ -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 diff --git a/state/state_test.go b/state/state_test.go index 162b8e9f76..6eae18de91 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -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 diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index 1776952b3b..27618ca368 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -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 diff --git a/tests/tmsp/tmsp_test.go b/tests/tmsp/tmsp_test.go index c00cadedbe..62f16eb6ea 100644 --- a/tests/tmsp/tmsp_test.go +++ b/tests/tmsp/tmsp_test.go @@ -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 diff --git a/testutils/testing.go b/testutils/testing.go index f91394a0e1..930b3a7149 100644 --- a/testutils/testing.go +++ b/testutils/testing.go @@ -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, diff --git a/types/account.go b/types/account.go index d1e62d8321..b3478fce0c 100644 --- a/types/account.go +++ b/types/account.go @@ -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 } diff --git a/types/tx.go b/types/tx.go index b8757e44aa..92f69d84fc 100644 --- a/types/tx.go +++ b/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,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 }