forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
REST tx endpoint backwards compatibility (cosmos#6801)
* update rest endpoints * Add conversion logic for auth encode/decode/broadcast * Cleanup * Add tx conversion to legacy REST tx endpoints. * Cleanup * Add tests * Add tests for ConvertAndEncodeStdTx * Fix for StdSignature * Test coverage improvements * Add integration test for REST broadcast Co-authored-by: Aaron Craelius <[email protected]> Co-authored-by: Aaron Craelius <[email protected]>
- Loading branch information
1 parent
8283165
commit c7ad21d
Showing
12 changed files
with
402 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package tx | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
"github.com/cosmos/cosmos-sdk/x/auth/types" | ||
) | ||
|
||
// ConvertTxToStdTx converts a transaction to the legacy StdTx format | ||
func ConvertTxToStdTx(codec *codec.Codec, tx signing.SigFeeMemoTx) (types.StdTx, error) { | ||
if stdTx, ok := tx.(types.StdTx); ok { | ||
return stdTx, nil | ||
} | ||
|
||
aminoTxConfig := types.StdTxConfig{Cdc: codec} | ||
builder := aminoTxConfig.NewTxBuilder() | ||
|
||
err := CopyTx(tx, builder) | ||
if err != nil { | ||
|
||
return types.StdTx{}, err | ||
} | ||
|
||
stdTx, ok := builder.GetTx().(types.StdTx) | ||
if !ok { | ||
return types.StdTx{}, fmt.Errorf("expected %T, got %+v", types.StdTx{}, builder.GetTx()) | ||
} | ||
|
||
return stdTx, nil | ||
} | ||
|
||
// CopyTx copies a SigFeeMemoTx to a new TxBuilder, allowing conversion between | ||
// different transaction formats. | ||
func CopyTx(tx signing.SigFeeMemoTx, builder client.TxBuilder) error { | ||
err := builder.SetMsgs(tx.GetMsgs()...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
sigs, err := tx.GetSignaturesV2() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = builder.SetSignatures(sigs...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
builder.SetMemo(tx.GetMemo()) | ||
builder.SetFeeAmount(tx.GetFee()) | ||
builder.SetGasLimit(tx.GetGas()) | ||
|
||
return nil | ||
} | ||
|
||
func ConvertAndEncodeStdTx(txConfig client.TxConfig, stdTx types.StdTx) ([]byte, error) { | ||
builder := txConfig.NewTxBuilder() | ||
|
||
var theTx sdk.Tx | ||
|
||
// check if we need a StdTx anyway, in that case don't copy | ||
if _, ok := builder.GetTx().(types.StdTx); ok { | ||
theTx = stdTx | ||
} else { | ||
err := CopyTx(stdTx, builder) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
theTx = builder.GetTx() | ||
} | ||
|
||
return txConfig.TxEncoder()(theTx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package tx_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/suite" | ||
|
||
"github.com/cosmos/cosmos-sdk/simapp/params" | ||
|
||
"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
tx2 "github.com/cosmos/cosmos-sdk/client/tx" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
"github.com/cosmos/cosmos-sdk/simapp" | ||
"github.com/cosmos/cosmos-sdk/std" | ||
"github.com/cosmos/cosmos-sdk/x/auth/tx" | ||
types3 "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
|
||
signing2 "github.com/cosmos/cosmos-sdk/types/tx/signing" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/testutil/testdata" | ||
"github.com/cosmos/cosmos-sdk/types" | ||
types2 "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
) | ||
|
||
const ( | ||
memo = "waboom" | ||
gas = uint64(10000) | ||
) | ||
|
||
var ( | ||
fee = types.NewCoins(types.NewInt64Coin("bam", 100)) | ||
_, pub1, addr1 = testdata.KeyTestPubAddr() | ||
_, _, addr2 = testdata.KeyTestPubAddr() | ||
msg = types2.NewMsgSend(addr1, addr2, types.NewCoins(types.NewInt64Coin("wack", 10000))) | ||
sig = signing2.SignatureV2{ | ||
PubKey: pub1, | ||
Data: &signing2.SingleSignatureData{ | ||
SignMode: signing2.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, | ||
Signature: []byte("dummy"), | ||
}, | ||
} | ||
) | ||
|
||
func buildTestTx(t *testing.T, builder client.TxBuilder) { | ||
builder.SetMemo(memo) | ||
builder.SetGasLimit(gas) | ||
builder.SetFeeAmount(fee) | ||
err := builder.SetMsgs(msg) | ||
require.NoError(t, err) | ||
err = builder.SetSignatures(sig) | ||
require.NoError(t, err) | ||
} | ||
|
||
type TestSuite struct { | ||
suite.Suite | ||
encCfg params.EncodingConfig | ||
protoCfg client.TxConfig | ||
aminoCfg client.TxConfig | ||
} | ||
|
||
func (s *TestSuite) SetupSuite() { | ||
encCfg := simapp.MakeEncodingConfig() | ||
s.encCfg = encCfg | ||
s.protoCfg = tx.NewTxConfig(codec.NewProtoCodec(encCfg.InterfaceRegistry), std.DefaultPublicKeyCodec{}, tx.DefaultSignModeHandler()) | ||
s.aminoCfg = types3.StdTxConfig{Cdc: encCfg.Amino} | ||
} | ||
|
||
func (s *TestSuite) TestCopyTx() { | ||
// proto -> amino -> proto | ||
protoBuilder := s.protoCfg.NewTxBuilder() | ||
buildTestTx(s.T(), protoBuilder) | ||
aminoBuilder := s.aminoCfg.NewTxBuilder() | ||
err := tx2.CopyTx(protoBuilder.GetTx(), aminoBuilder) | ||
s.Require().NoError(err) | ||
protoBuilder2 := s.protoCfg.NewTxBuilder() | ||
err = tx2.CopyTx(aminoBuilder.GetTx(), protoBuilder2) | ||
s.Require().NoError(err) | ||
bz, err := s.protoCfg.TxEncoder()(protoBuilder.GetTx()) | ||
s.Require().NoError(err) | ||
bz2, err := s.protoCfg.TxEncoder()(protoBuilder2.GetTx()) | ||
s.Require().NoError(err) | ||
s.Require().Equal(bz, bz2) | ||
|
||
// amino -> proto -> amino | ||
aminoBuilder = s.aminoCfg.NewTxBuilder() | ||
buildTestTx(s.T(), aminoBuilder) | ||
protoBuilder = s.protoCfg.NewTxBuilder() | ||
err = tx2.CopyTx(aminoBuilder.GetTx(), protoBuilder) | ||
s.Require().NoError(err) | ||
aminoBuilder2 := s.aminoCfg.NewTxBuilder() | ||
err = tx2.CopyTx(protoBuilder.GetTx(), aminoBuilder2) | ||
s.Require().NoError(err) | ||
bz, err = s.aminoCfg.TxEncoder()(aminoBuilder.GetTx()) | ||
s.Require().NoError(err) | ||
bz2, err = s.aminoCfg.TxEncoder()(aminoBuilder2.GetTx()) | ||
s.Require().NoError(err) | ||
s.Require().Equal(bz, bz2) | ||
} | ||
|
||
func (s *TestSuite) TestConvertTxToStdTx() { | ||
// proto tx | ||
protoBuilder := s.protoCfg.NewTxBuilder() | ||
buildTestTx(s.T(), protoBuilder) | ||
stdTx, err := tx2.ConvertTxToStdTx(s.encCfg.Amino, protoBuilder.GetTx()) | ||
s.Require().NoError(err) | ||
s.Require().Equal(memo, stdTx.Memo) | ||
s.Require().Equal(gas, stdTx.Fee.Gas) | ||
s.Require().Equal(fee, stdTx.Fee.Amount) | ||
s.Require().Equal(msg, stdTx.Msgs[0]) | ||
s.Require().Equal(sig.PubKey, stdTx.Signatures[0].PubKey) | ||
s.Require().Equal(sig.Data.(*signing2.SingleSignatureData).Signature, stdTx.Signatures[0].Signature) | ||
|
||
// std tx | ||
aminoBuilder := s.aminoCfg.NewTxBuilder() | ||
buildTestTx(s.T(), aminoBuilder) | ||
stdTx = aminoBuilder.GetTx().(types3.StdTx) | ||
stdTx2, err := tx2.ConvertTxToStdTx(s.encCfg.Amino, stdTx) | ||
s.Require().NoError(err) | ||
s.Require().Equal(stdTx, stdTx2) | ||
} | ||
|
||
func (s *TestSuite) TestConvertAndEncodeStdTx() { | ||
// convert amino -> proto -> amino | ||
aminoBuilder := s.aminoCfg.NewTxBuilder() | ||
buildTestTx(s.T(), aminoBuilder) | ||
stdTx := aminoBuilder.GetTx().(types3.StdTx) | ||
txBz, err := tx2.ConvertAndEncodeStdTx(s.protoCfg, stdTx) | ||
s.Require().NoError(err) | ||
decodedTx, err := s.protoCfg.TxDecoder()(txBz) | ||
s.Require().NoError(err) | ||
aminoBuilder2 := s.aminoCfg.NewTxBuilder() | ||
s.Require().NoError(tx2.CopyTx(decodedTx.(signing.SigFeeMemoTx), aminoBuilder2)) | ||
s.Require().Equal(stdTx, aminoBuilder2.GetTx()) | ||
|
||
// just use amino everywhere | ||
txBz, err = tx2.ConvertAndEncodeStdTx(s.aminoCfg, stdTx) | ||
s.Require().NoError(err) | ||
decodedTx, err = s.aminoCfg.TxDecoder()(txBz) | ||
s.Require().NoError(err) | ||
s.Require().Equal(stdTx, decodedTx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.