forked from cerc-io/laconicd-deprecated
		
	Remove EmbeddedTx and related logic
This commit is contained in:
		
							parent
							
								
									8b642e3f46
								
							
						
					
					
						commit
						cd593e3e37
					
				
							
								
								
									
										54
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										54
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							| @ -3,19 +3,19 @@ | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
|   digest = "1:fcdf62d2d7e43c2565d6f8707ab4eae54dac702ed4bafb194b85139f0508929f" | ||||
|   digest = "1:79b02529d2120af44eaad5f7fee9ff7e003739d469e2c2767008b797d290e9fd" | ||||
|   name = "github.com/aristanetworks/goarista" | ||||
|   packages = ["monotime"] | ||||
|   pruneopts = "T" | ||||
|   revision = "b2d71c282dc706f4b4f6c15b65810e1202ecd53f" | ||||
|   revision = "18b896026201d8e1758468d9c5d5a558c69c5e9b" | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
|   digest = "1:d4d66abd43dbb9b5f5e6a176c5ed279c289f8db734904c047d95113a04aa2e60" | ||||
|   digest = "1:8ad24ea05e770b745b5c286b4f94cf73d5be87005680e36b2d0dd1de0a2f9fbf" | ||||
|   name = "github.com/btcsuite/btcd" | ||||
|   packages = ["btcec"] | ||||
|   pruneopts = "T" | ||||
|   revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" | ||||
|   revision = "d81d8877b8f327112e94e814937143a71d1692a7" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:d0d998526cfb68788229a31c16a557fdf1fbbb510654be6b3732c2758e06b533" | ||||
| @ -25,7 +25,7 @@ | ||||
|   revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:36773b598dec105de46a87978ae14e64c8d2c45aa556b8e0ddfc62d6abc7c47e" | ||||
|   digest = "1:bc28e755cf6a9fd8e65497514d20c4907973e7a6a6409d30ead3fd37bfeb19a9" | ||||
|   name = "github.com/cosmos/cosmos-sdk" | ||||
|   packages = [ | ||||
|     "baseapp", | ||||
| @ -36,16 +36,16 @@ | ||||
|     "x/auth", | ||||
|   ] | ||||
|   pruneopts = "T" | ||||
|   revision = "23e3d5ac12145c02fcb4b4767d7dfccad782aee5" | ||||
|   version = "v0.23.1" | ||||
|   revision = "1c38c70468ec721e3a555ba2f3bf5f9da31f0cc9" | ||||
|   version = "v0.24.2" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:52f195ad0e20a92d8604c1ba3cd246c61644c03eaa454b5acd41be89841e0d10" | ||||
|   digest = "1:9f42202ac457c462ad8bb9642806d275af9ab4850cf0b1960b9c6f083d4a309a" | ||||
|   name = "github.com/davecgh/go-spew" | ||||
|   packages = ["spew"] | ||||
|   pruneopts = "T" | ||||
|   revision = "346938d642f2ec3594ed81d874461961cd0faa76" | ||||
|   version = "v1.1.0" | ||||
|   revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" | ||||
|   version = "v1.1.1" | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
| @ -224,12 +224,12 @@ | ||||
|   version = "v0.0.3" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:6de2f73eb31e80d74f84ce1c861e4c0c8f00ca5fb41a25901f987e63a0647c28" | ||||
|   digest = "1:9ba911fe3884995431690e7eb180cf848da0d637ba5f61711783b795d031793f" | ||||
|   name = "github.com/spf13/pflag" | ||||
|   packages = ["."] | ||||
|   pruneopts = "T" | ||||
|   revision = "583c0c0531f06d5278b7d917446061adc344b5cd" | ||||
|   version = "v1.0.1" | ||||
|   revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" | ||||
|   version = "v1.0.2" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:e95496462101745805bd4e041a5b841e108c7cf761264d53648246308de2761e" | ||||
| @ -245,7 +245,7 @@ | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
|   digest = "1:7d44c4d11eb65cfdc78c76040f37ef305b16474c019c98a8a7cf188fece2d574" | ||||
|   digest = "1:ee395d0d8c1719b5a1407f34af93953b4763bacb19a8961aba5b6d312824da41" | ||||
|   name = "github.com/syndtr/goleveldb" | ||||
|   packages = [ | ||||
|     "leveldb", | ||||
| @ -262,7 +262,7 @@ | ||||
|     "leveldb/util", | ||||
|   ] | ||||
|   pruneopts = "T" | ||||
|   revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" | ||||
|   revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
| @ -276,14 +276,6 @@ | ||||
|   pruneopts = "T" | ||||
|   revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
|   digest = "1:3a6bdd02e7f2585c860e368467c5989310740af6206a1ada85cfa19c712e5afd" | ||||
|   name = "github.com/tendermint/ethermint" | ||||
|   packages = ["version"] | ||||
|   pruneopts = "T" | ||||
|   revision = "c1e6ebf80a6cc9119bc178faee18ef13490d707a" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:0e2addab3f64ece97ca434b2bf2d4e8cb54a4509904a03be8c81da3fc2ddb245" | ||||
|   name = "github.com/tendermint/go-amino" | ||||
| @ -301,7 +293,7 @@ | ||||
|   version = "v0.9.2" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:9f6704ae2aedbadf616e5850375c504909d46b6ea57d4679de2b7cbc715f08e1" | ||||
|   digest = "1:5a60cb048b401c0263c227baf8778ecaf038be531707057607949540486874ef" | ||||
|   name = "github.com/tendermint/tendermint" | ||||
|   packages = [ | ||||
|     "abci/server", | ||||
| @ -321,16 +313,16 @@ | ||||
|     "types", | ||||
|   ] | ||||
|   pruneopts = "T" | ||||
|   revision = "d542d2c3945116697f60451e6a407082c41c3cc9" | ||||
|   version = "v0.22.8" | ||||
|   revision = "81df19e68ab1519399fccf0cab81cb75bf9d782e" | ||||
|   version = "v0.23.1-rc0" | ||||
| 
 | ||||
| [[projects]] | ||||
|   branch = "master" | ||||
|   digest = "1:2cbe8758697d867fcebf73bcc69dff8e8abaa7fd65e5704e0744e522ccff4e6a" | ||||
|   digest = "1:da29cbeb9d244918393b37243c008ab7128688fb017c966aaf876587c010bcdd" | ||||
|   name = "golang.org/x/crypto" | ||||
|   packages = ["ripemd160"] | ||||
|   pruneopts = "T" | ||||
|   revision = "f027049dab0ad238e394a753dba2d14753473a04" | ||||
|   revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:5fdc7adede42f80d6201258355d478d856778e21d735f14972abd8ff793fdbf7" | ||||
| @ -372,11 +364,12 @@ | ||||
|   version = "v0.3.0" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:8cfa91d1b7f6b66fa9b1a738a4bc1325837b861e63fb9a2919931d68871bb770" | ||||
|   branch = "master" | ||||
|   digest = "1:960f1fa3f12667fe595c15c12523718ed8b1b5428c83d70da54bb014da9a4c1a" | ||||
|   name = "google.golang.org/genproto" | ||||
|   packages = ["googleapis/rpc/status"] | ||||
|   pruneopts = "T" | ||||
|   revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" | ||||
|   revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:adafc60b1d4688759f3fc8f9089e71dd17abd123f4729de6b913bf08c9143770" | ||||
| @ -466,7 +459,6 @@ | ||||
|     "github.com/pkg/errors", | ||||
|     "github.com/stretchr/testify/require", | ||||
|     "github.com/stretchr/testify/suite", | ||||
|     "github.com/tendermint/ethermint/version", | ||||
|     "github.com/tendermint/tendermint/libs/common", | ||||
|     "github.com/tendermint/tendermint/libs/db", | ||||
|     "github.com/tendermint/tendermint/libs/log", | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| 
 | ||||
| [[constraint]] | ||||
|   name = "github.com/cosmos/cosmos-sdk" | ||||
|   version = "=0.23.1" | ||||
|   version = "=0.24.2" | ||||
| 
 | ||||
| [[constraint]] | ||||
|   name = "github.com/hashicorp/golang-lru" | ||||
| @ -15,12 +15,12 @@ | ||||
|   version = "~0.0.1" | ||||
| 
 | ||||
| [[override]] | ||||
|   name = "google.golang.org/genproto" | ||||
|   revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" | ||||
|   name = "github.com/tendermint/iavl" | ||||
|   version = "=v0.9.2" | ||||
| 
 | ||||
| [[override]] | ||||
|   name = "github.com/tendermint/tendermint" | ||||
|   version = "=v0.22.8" | ||||
|   version = "=v0.23.1-rc0" | ||||
| 
 | ||||
| [[constraint]] | ||||
|   name = "github.com/stretchr/testify" | ||||
|  | ||||
| @ -26,11 +26,10 @@ type internalAnteHandler func( | ||||
| 	sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper, | ||||
| ) (newCtx sdk.Context, res sdk.Result, abort bool) | ||||
| 
 | ||||
| // AnteHandler handles Ethereum transactions and passes SDK transactions to the
 | ||||
| // embeddedAnteHandler if it's an Ethermint transaction. The ante handler gets
 | ||||
| // invoked after the BaseApp performs the runTx. At this point, the transaction
 | ||||
| // should be properly decoded via the TxDecoder and should be of a proper type,
 | ||||
| // Transaction or EmbeddedTx.
 | ||||
| // AnteHandler is responsible for attempting to route an Ethereum or SDK
 | ||||
| // transaction to an internal ante handler for performing transaction-level
 | ||||
| // processing (e.g. fee payment, signature verification) before being passed
 | ||||
| // onto it's respective handler.
 | ||||
| func AnteHandler(am auth.AccountMapper) sdk.AnteHandler { | ||||
| 	return func(sdkCtx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { | ||||
| 		var ( | ||||
| @ -42,7 +41,7 @@ func AnteHandler(am auth.AccountMapper) sdk.AnteHandler { | ||||
| 		case types.Transaction: | ||||
| 			gasLimit = int64(tx.Data.GasLimit) | ||||
| 			handler = handleEthTx | ||||
| 		case types.EmbeddedTx: | ||||
| 		case auth.StdTx: | ||||
| 			gasLimit = tx.Fee.Gas | ||||
| 			handler = handleEmbeddedTx | ||||
| 		default: | ||||
| @ -107,23 +106,23 @@ func handleEthTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Cont | ||||
| // handleEmbeddedTx implements an ante handler for an SDK transaction. It
 | ||||
| // validates the signature and if valid returns an OK result.
 | ||||
| func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Context, sdk.Result, bool) { | ||||
| 	etx, ok := tx.(types.EmbeddedTx) | ||||
| 	stdTx, ok := tx.(auth.StdTx) | ||||
| 	if !ok { | ||||
| 		return sdkCtx, sdk.ErrInternal(fmt.Sprintf("invalid transaction: %T", tx)).Result(), true | ||||
| 	} | ||||
| 
 | ||||
| 	if err := validateEmbeddedTxBasic(etx); err != nil { | ||||
| 	if err := validateStdTxBasic(stdTx); err != nil { | ||||
| 		return sdkCtx, err.Result(), true | ||||
| 	} | ||||
| 
 | ||||
| 	signerAddrs := etx.GetRequiredSigners() | ||||
| 	signerAddrs := stdTx.GetSigners() | ||||
| 	signerAccs := make([]auth.Account, len(signerAddrs)) | ||||
| 
 | ||||
| 	// validate signatures
 | ||||
| 	for i, sig := range etx.Signatures { | ||||
| 	for i, sig := range stdTx.Signatures { | ||||
| 		signer := ethcmn.BytesToAddress(signerAddrs[i].Bytes()) | ||||
| 
 | ||||
| 		signerAcc, err := validateSignature(sdkCtx, etx, signer, sig, am) | ||||
| 		signerAcc, err := validateSignature(sdkCtx, stdTx, signer, sig, am) | ||||
| 		if err.Code() != sdk.CodeOK { | ||||
| 			return sdkCtx, err.Result(), false | ||||
| 		} | ||||
| @ -136,18 +135,18 @@ func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk | ||||
| 
 | ||||
| 	newCtx := auth.WithSigners(sdkCtx, signerAccs) | ||||
| 
 | ||||
| 	return newCtx, sdk.Result{GasWanted: etx.Fee.Gas}, false | ||||
| 	return newCtx, sdk.Result{GasWanted: stdTx.Fee.Gas}, false | ||||
| } | ||||
| 
 | ||||
| // validateEmbeddedTxBasic validates an EmbeddedTx based on things that don't
 | ||||
| // validateStdTxBasic validates an auth.StdTx based on parameters that do not
 | ||||
| // depend on the context.
 | ||||
| func validateEmbeddedTxBasic(etx types.EmbeddedTx) (err sdk.Error) { | ||||
| 	sigs := etx.Signatures | ||||
| func validateStdTxBasic(stdTx auth.StdTx) (err sdk.Error) { | ||||
| 	sigs := stdTx.Signatures | ||||
| 	if len(sigs) == 0 { | ||||
| 		return sdk.ErrUnauthorized("transaction missing signatures") | ||||
| 	} | ||||
| 
 | ||||
| 	signerAddrs := etx.GetRequiredSigners() | ||||
| 	signerAddrs := stdTx.GetSigners() | ||||
| 	if len(sigs) != len(signerAddrs) { | ||||
| 		return sdk.ErrUnauthorized("invalid number of transaction signers") | ||||
| 	} | ||||
| @ -156,8 +155,8 @@ func validateEmbeddedTxBasic(etx types.EmbeddedTx) (err sdk.Error) { | ||||
| } | ||||
| 
 | ||||
| func validateSignature( | ||||
| 	sdkCtx sdk.Context, etx types.EmbeddedTx, signer ethcmn.Address, | ||||
| 	sig []byte, am auth.AccountMapper, | ||||
| 	sdkCtx sdk.Context, stdTx auth.StdTx, signer ethcmn.Address, | ||||
| 	sig auth.StdSignature, am auth.AccountMapper, | ||||
| ) (acc auth.Account, sdkErr sdk.Error) { | ||||
| 
 | ||||
| 	chainID := sdkCtx.ChainID() | ||||
| @ -167,28 +166,29 @@ func validateSignature( | ||||
| 		return nil, sdk.ErrUnknownAddress(fmt.Sprintf("no account with address %s found", signer)) | ||||
| 	} | ||||
| 
 | ||||
| 	signEtx := types.EmbeddedTxSign{ | ||||
| 		ChainID:       chainID, | ||||
| 		AccountNumber: acc.GetAccountNumber(), | ||||
| 		Sequence:      acc.GetSequence(), | ||||
| 		Messages:      etx.Messages, | ||||
| 		Fee:           etx.Fee, | ||||
| 	accNum := acc.GetAccountNumber() | ||||
| 	if accNum != sig.AccountNumber { | ||||
| 		return nil, sdk.ErrInvalidSequence( | ||||
| 			fmt.Sprintf("invalid account number; got %d, expected %d", sig.AccountNumber, accNum)) | ||||
| 	} | ||||
| 
 | ||||
| 	err := acc.SetSequence(signEtx.Sequence + 1) | ||||
| 	accSeq := acc.GetSequence() | ||||
| 	if accSeq != sig.Sequence { | ||||
| 		return nil, sdk.ErrInvalidSequence( | ||||
| 			fmt.Sprintf("invalid account sequence; got %d, expected %d", sig.Sequence, accSeq)) | ||||
| 	} | ||||
| 
 | ||||
| 	err := acc.SetSequence(accSeq + 1) | ||||
| 	if err != nil { | ||||
| 		return nil, sdk.ErrInternal(err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	signBytes, err := signEtx.Bytes() | ||||
| 	if err != nil { | ||||
| 		return nil, sdk.ErrInternal(err.Error()) | ||||
| 	} | ||||
| 	signBytes := types.GetStdTxSignBytes(chainID, accNum, accSeq, stdTx.Fee, stdTx.GetMsgs(), stdTx.Memo) | ||||
| 
 | ||||
| 	// consume gas for signature verification
 | ||||
| 	sdkCtx.GasMeter().ConsumeGas(verifySigCost, "ante verify") | ||||
| 	sdkCtx.GasMeter().ConsumeGas(verifySigCost, "ante signature verification") | ||||
| 
 | ||||
| 	if err := types.ValidateSigner(signBytes, sig, signer); err != nil { | ||||
| 	if err := types.ValidateSigner(signBytes, sig.Signature, signer); err != nil { | ||||
| 		return nil, sdk.ErrUnauthorized(err.Error()) | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										158
									
								
								types/tx.go
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								types/tx.go
									
									
									
									
									
								
							| @ -1,17 +1,13 @@ | ||||
| package types | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"sync/atomic" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/cosmos/cosmos-sdk/wire" | ||||
| 	"github.com/cosmos/cosmos-sdk/x/auth" | ||||
| 	ethcmn "github.com/ethereum/go-ethereum/common" | ||||
| 	ethtypes "github.com/ethereum/go-ethereum/core/types" | ||||
| 	ethcrypto "github.com/ethereum/go-ethereum/crypto" | ||||
| @ -26,13 +22,9 @@ const ( | ||||
| 	TypeTxEthereum = "Ethereum" | ||||
| ) | ||||
| 
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| // Ethereum transaction
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| type ( | ||||
| 	// Transaction implements the Ethereum transaction structure as an exact
 | ||||
| 	// copy. It implements the Cosmos sdk.Tx interface. Due to the private
 | ||||
| 	// replica. It implements the Cosmos sdk.Tx interface. Due to the private
 | ||||
| 	// fields, it must be replicated here and cannot be embedded or used
 | ||||
| 	// directly.
 | ||||
| 	//
 | ||||
| @ -47,9 +39,7 @@ type ( | ||||
| 		from atomic.Value | ||||
| 	} | ||||
| 
 | ||||
| 	// TxData implements the Ethereum transaction data structure as an exact
 | ||||
| 	// copy. It is used solely as intended in Ethereum abiding by the protocol
 | ||||
| 	// except for the payload field which may embed a Cosmos SDK transaction.
 | ||||
| 	// TxData defines internal Ethereum transaction information
 | ||||
| 	TxData struct { | ||||
| 		AccountNonce uint64          `json:"nonce"` | ||||
| 		Price        sdk.Int         `json:"gasPrice"` | ||||
| @ -204,6 +194,8 @@ func (tx Transaction) GetMsgs() []sdk.Msg { | ||||
| // with the signature set. The signature if first recovered and then a new
 | ||||
| // Transaction is created with that signature. If setting the signature fails,
 | ||||
| // a panic will be triggered.
 | ||||
| //
 | ||||
| // TODO: To be removed in #470
 | ||||
| func (tx Transaction) ConvertTx(chainID *big.Int) ethtypes.Transaction { | ||||
| 	gethTx := ethtypes.NewTransaction( | ||||
| 		tx.Data.AccountNonce, *tx.Data.Recipient, tx.Data.Amount.BigInt(), | ||||
| @ -221,139 +213,16 @@ func (tx Transaction) ConvertTx(chainID *big.Int) ethtypes.Transaction { | ||||
| 	return *gethTx | ||||
| } | ||||
| 
 | ||||
| // HasEmbeddedTx returns a boolean reflecting if the transaction contains an
 | ||||
| // SDK transaction or not based on the recipient address.
 | ||||
| func (tx Transaction) HasEmbeddedTx(addr ethcmn.Address) bool { | ||||
| 	return bytes.Equal(tx.Data.Recipient.Bytes(), addr.Bytes()) | ||||
| } | ||||
| 
 | ||||
| // GetEmbeddedTx returns the embedded SDK transaction from an Ethereum
 | ||||
| // transaction. It returns an error if decoding the inner transaction fails.
 | ||||
| //
 | ||||
| // CONTRACT: The payload field of an Ethereum transaction must contain a valid
 | ||||
| // encoded SDK transaction.
 | ||||
| func (tx Transaction) GetEmbeddedTx(codec *wire.Codec) (EmbeddedTx, sdk.Error) { | ||||
| 	etx := EmbeddedTx{} | ||||
| 
 | ||||
| 	err := codec.UnmarshalBinary(tx.Data.Payload, &etx) | ||||
| 	if err != nil { | ||||
| 		return EmbeddedTx{}, sdk.ErrTxDecode("failed to encode embedded tx") | ||||
| 	} | ||||
| 
 | ||||
| 	return etx, nil | ||||
| } | ||||
| 
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| // embedded SDK transaction
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| type ( | ||||
| 	// EmbeddedTx implements an SDK transaction. It is to be encoded into the
 | ||||
| 	// payload field of an Ethereum transaction in order to route and handle SDK
 | ||||
| 	// transactions.
 | ||||
| 	EmbeddedTx struct { | ||||
| 		Messages   []sdk.Msg   `json:"messages"` | ||||
| 		Fee        auth.StdFee `json:"fee"` | ||||
| 		Signatures [][]byte    `json:"signatures"` | ||||
| 	} | ||||
| 
 | ||||
| 	// embeddedSignDoc implements a simple SignDoc for a EmbeddedTx signer to
 | ||||
| 	// sign over.
 | ||||
| 	embeddedSignDoc struct { | ||||
| 		ChainID       string            `json:"chainID"` | ||||
| 		AccountNumber int64             `json:"accountNumber"` | ||||
| 		Sequence      int64             `json:"sequence"` | ||||
| 		Messages      []json.RawMessage `json:"messages"` | ||||
| 		Fee           json.RawMessage   `json:"fee"` | ||||
| 	} | ||||
| 
 | ||||
| 	// EmbeddedTxSign implements a structure for containing the information
 | ||||
| 	// necessary for building and signing an EmbeddedTx.
 | ||||
| 	EmbeddedTxSign struct { | ||||
| 		ChainID       string | ||||
| 		AccountNumber int64 | ||||
| 		Sequence      int64 | ||||
| 		Messages      []sdk.Msg | ||||
| 		Fee           auth.StdFee | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| // GetMsgs implements the sdk.Tx interface. It returns all the SDK transaction
 | ||||
| // messages.
 | ||||
| func (etx EmbeddedTx) GetMsgs() []sdk.Msg { | ||||
| 	return etx.Messages | ||||
| } | ||||
| 
 | ||||
| // GetRequiredSigners returns all the required signers of an SDK transaction
 | ||||
| // accumulated from messages. It returns them in a deterministic fashion given
 | ||||
| // a list of messages.
 | ||||
| func (etx EmbeddedTx) GetRequiredSigners() []sdk.AccAddress { | ||||
| 	seen := map[string]bool{} | ||||
| 
 | ||||
| 	var signers []sdk.AccAddress | ||||
| 	for _, msg := range etx.GetMsgs() { | ||||
| 		for _, addr := range msg.GetSigners() { | ||||
| 			if !seen[addr.String()] { | ||||
| 				signers = append(signers, sdk.AccAddress(addr)) | ||||
| 				seen[addr.String()] = true | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return signers | ||||
| } | ||||
| 
 | ||||
| // Bytes returns the EmbeddedTxSign signature bytes for a signer to sign over.
 | ||||
| func (ets EmbeddedTxSign) Bytes() ([]byte, error) { | ||||
| 	sigBytes, err := EmbeddedSignBytes(ets.ChainID, ets.AccountNumber, ets.Sequence, ets.Messages, ets.Fee) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	hash := sha256.Sum256(sigBytes) | ||||
| 	return hash[:], nil | ||||
| } | ||||
| 
 | ||||
| // EmbeddedSignBytes creates signature bytes for a signer to sign an embedded
 | ||||
| // transaction. The signature bytes require a chainID and an account number.
 | ||||
| // The signature bytes are JSON encoded.
 | ||||
| func EmbeddedSignBytes(chainID string, accnum, sequence int64, msgs []sdk.Msg, fee auth.StdFee) ([]byte, error) { | ||||
| 	var msgsBytes []json.RawMessage | ||||
| 	for _, msg := range msgs { | ||||
| 		msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes())) | ||||
| 	} | ||||
| 
 | ||||
| 	signDoc := embeddedSignDoc{ | ||||
| 		ChainID:       chainID, | ||||
| 		AccountNumber: accnum, | ||||
| 		Sequence:      sequence, | ||||
| 		Messages:      msgsBytes, | ||||
| 		Fee:           json.RawMessage(fee.Bytes()), | ||||
| 	} | ||||
| 
 | ||||
| 	bz, err := typesCodec.MarshalJSON(signDoc) | ||||
| 	if err != nil { | ||||
| 		errors.Wrap(err, "failed to JSON encode EmbeddedSignDoc") | ||||
| 	} | ||||
| 
 | ||||
| 	return bz, nil | ||||
| } | ||||
| 
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| // Utilities
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| // TxDecoder returns an sdk.TxDecoder that given raw transaction bytes,
 | ||||
| // attempts to decode them into a Transaction or an EmbeddedTx or returning an
 | ||||
| // error if decoding fails.
 | ||||
| func TxDecoder(codec *wire.Codec, sdkAddress ethcmn.Address) sdk.TxDecoder { | ||||
| // attempts to decode them into a valid sdk.Tx.
 | ||||
| func TxDecoder(codec *wire.Codec) sdk.TxDecoder { | ||||
| 	return func(txBytes []byte) (sdk.Tx, sdk.Error) { | ||||
| 		var tx = Transaction{} | ||||
| 
 | ||||
| 		if len(txBytes) == 0 { | ||||
| 			return nil, sdk.ErrTxDecode("txBytes are empty") | ||||
| 		} | ||||
| 
 | ||||
| 		var tx sdk.Tx | ||||
| 
 | ||||
| 		// The given codec should have all the appropriate message types
 | ||||
| 		// registered.
 | ||||
| 		err := codec.UnmarshalBinary(txBytes, &tx) | ||||
| @ -361,17 +230,6 @@ func TxDecoder(codec *wire.Codec, sdkAddress ethcmn.Address) sdk.TxDecoder { | ||||
| 			return nil, sdk.ErrTxDecode("failed to decode tx").TraceSDK(err.Error()) | ||||
| 		} | ||||
| 
 | ||||
| 		// If the transaction is routed as an SDK transaction, decode and
 | ||||
| 		// return the embedded transaction.
 | ||||
| 		if tx.HasEmbeddedTx(sdkAddress) { | ||||
| 			etx, err := tx.GetEmbeddedTx(codec) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
| 			return etx, nil | ||||
| 		} | ||||
| 
 | ||||
| 		return tx, nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										186
									
								
								types/tx_test.go
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								types/tx_test.go
									
									
									
									
									
								
							| @ -3,14 +3,12 @@ package types | ||||
| import ( | ||||
| 	"crypto/ecdsa" | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/cosmos/cosmos-sdk/wire" | ||||
| 	"github.com/cosmos/cosmos-sdk/x/auth" | ||||
| 	ethcmn "github.com/ethereum/go-ethereum/common" | ||||
| 	ethtypes "github.com/ethereum/go-ethereum/core/types" | ||||
| 	ethcrypto "github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
| @ -23,64 +21,42 @@ var ( | ||||
| 
 | ||||
| 	testAddr1 = PrivKeyToEthAddress(testPrivKey1) | ||||
| 	testAddr2 = PrivKeyToEthAddress(testPrivKey2) | ||||
| 
 | ||||
| 	testSDKAddress = GenerateEthAddress() | ||||
| ) | ||||
| 
 | ||||
| func newTestCodec() *wire.Codec { | ||||
| 	codec := wire.NewCodec() | ||||
| 
 | ||||
| 	RegisterWire(codec) | ||||
| 	codec.RegisterConcrete(auth.StdTx{}, "test/StdTx", nil) | ||||
| 	codec.RegisterConcrete(&sdk.TestMsg{}, "test/TestMsg", nil) | ||||
| 	wire.RegisterCrypto(codec) | ||||
| 
 | ||||
| 	return codec | ||||
| } | ||||
| 
 | ||||
| func newStdFee() auth.StdFee { | ||||
| 	return auth.NewStdFee(5000, sdk.NewCoin("photon", 150)) | ||||
| 	return auth.NewStdFee(5000, sdk.NewCoin("photon", sdk.NewInt(150))) | ||||
| } | ||||
| 
 | ||||
| func newTestEmbeddedTx( | ||||
| func newTestStdTx( | ||||
| 	chainID sdk.Int, msgs []sdk.Msg, pKeys []*ecdsa.PrivateKey, | ||||
| 	accNums []int64, seqs []int64, fee auth.StdFee, | ||||
| ) sdk.Tx { | ||||
| 
 | ||||
| 	sigs := make([][]byte, len(pKeys)) | ||||
| 	sigs := make([]auth.StdSignature, len(pKeys)) | ||||
| 
 | ||||
| 	for i, priv := range pKeys { | ||||
| 		signEtx := EmbeddedTxSign{chainID.String(), accNums[i], seqs[i], msgs, newStdFee()} | ||||
| 
 | ||||
| 		signBytes, err := signEtx.Bytes() | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		signBytes := GetStdTxSignBytes(chainID.String(), accNums[i], seqs[i], newStdFee(), msgs, "") | ||||
| 
 | ||||
| 		sig, err := ethcrypto.Sign(signBytes, priv) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 
 | ||||
| 		sigs[i] = sig | ||||
| 		sigs[i] = auth.StdSignature{Signature: sig, AccountNumber: accNums[i], Sequence: seqs[i]} | ||||
| 	} | ||||
| 
 | ||||
| 	return EmbeddedTx{msgs, fee, sigs} | ||||
| } | ||||
| 
 | ||||
| func newTestGethTxs(chainID sdk.Int, pKeys []*ecdsa.PrivateKey, addrs []ethcmn.Address) []ethtypes.Transaction { | ||||
| 	txs := make([]ethtypes.Transaction, len(pKeys)) | ||||
| 
 | ||||
| 	for i, priv := range pKeys { | ||||
| 		ethTx := ethtypes.NewTransaction( | ||||
| 			uint64(i), addrs[i], big.NewInt(10), 100, big.NewInt(100), nil, | ||||
| 		) | ||||
| 
 | ||||
| 		signer := ethtypes.NewEIP155Signer(chainID.BigInt()) | ||||
| 		ethTx, _ = ethtypes.SignTx(ethTx, signer, priv) | ||||
| 
 | ||||
| 		txs[i] = *ethTx | ||||
| 	} | ||||
| 
 | ||||
| 	return txs | ||||
| 	return auth.NewStdTx(msgs, fee, sigs, "") | ||||
| } | ||||
| 
 | ||||
| func newTestEthTxs(chainID sdk.Int, pKeys []*ecdsa.PrivateKey, addrs []ethcmn.Address) []Transaction { | ||||
| @ -99,63 +75,6 @@ func newTestEthTxs(chainID sdk.Int, pKeys []*ecdsa.PrivateKey, addrs []ethcmn.Ad | ||||
| 	return txs | ||||
| } | ||||
| 
 | ||||
| func newTestSDKTxs( | ||||
| 	codec *wire.Codec, chainID sdk.Int, msgs []sdk.Msg, pKeys []*ecdsa.PrivateKey, | ||||
| 	accNums []int64, seqs []int64, fee auth.StdFee, | ||||
| ) []Transaction { | ||||
| 
 | ||||
| 	txs := make([]Transaction, len(pKeys)) | ||||
| 	etx := newTestEmbeddedTx(chainID, msgs, pKeys, accNums, seqs, fee) | ||||
| 
 | ||||
| 	for i, priv := range pKeys { | ||||
| 		payload := codec.MustMarshalBinary(etx) | ||||
| 
 | ||||
| 		emintTx := NewTransaction( | ||||
| 			uint64(i), testSDKAddress, sdk.NewInt(10), 100, | ||||
| 			sdk.NewInt(100), payload, | ||||
| 		) | ||||
| 
 | ||||
| 		emintTx.Sign(testChainID, priv) | ||||
| 
 | ||||
| 		txs[i] = emintTx | ||||
| 	} | ||||
| 
 | ||||
| 	return txs | ||||
| } | ||||
| 
 | ||||
| func TestConvertTx(t *testing.T) { | ||||
| 	gethTxs := newTestGethTxs( | ||||
| 		testChainID, | ||||
| 		[]*ecdsa.PrivateKey{testPrivKey1, testPrivKey2}, | ||||
| 		[]ethcmn.Address{testAddr1, testAddr2}, | ||||
| 	) | ||||
| 	ethTxs := newTestEthTxs( | ||||
| 		testChainID, | ||||
| 		[]*ecdsa.PrivateKey{testPrivKey1, testPrivKey2}, | ||||
| 		[]ethcmn.Address{testAddr1, testAddr2}, | ||||
| 	) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		ethTx      ethtypes.Transaction | ||||
| 		emintTx    Transaction | ||||
| 		expectedEq bool | ||||
| 	}{ | ||||
| 		{gethTxs[0], ethTxs[0], true}, | ||||
| 		{gethTxs[0], ethTxs[1], false}, | ||||
| 		{gethTxs[1], ethTxs[0], false}, | ||||
| 	} | ||||
| 
 | ||||
| 	for i, tc := range testCases { | ||||
| 		convertedTx := tc.emintTx.ConvertTx(testChainID.BigInt()) | ||||
| 
 | ||||
| 		if tc.expectedEq { | ||||
| 			require.Equal(t, tc.ethTx, convertedTx, fmt.Sprintf("unexpected result: test case #%d", i)) | ||||
| 		} else { | ||||
| 			require.NotEqual(t, tc.ethTx, convertedTx, fmt.Sprintf("unexpected result: test case #%d", i)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestValidation(t *testing.T) { | ||||
| 	ethTxs := newTestEthTxs( | ||||
| 		testChainID, | ||||
| @ -193,47 +112,6 @@ func TestValidation(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestHasEmbeddedTx(t *testing.T) { | ||||
| 	testCodec := newTestCodec() | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 
 | ||||
| 	sdkTxs := newTestSDKTxs( | ||||
| 		testCodec, testChainID, msgs, []*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]int64{0}, []int64{0}, newStdFee(), | ||||
| 	) | ||||
| 	require.True(t, sdkTxs[0].HasEmbeddedTx(testSDKAddress)) | ||||
| 
 | ||||
| 	ethTxs := newTestEthTxs( | ||||
| 		testChainID, | ||||
| 		[]*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]ethcmn.Address{testAddr1}, | ||||
| 	) | ||||
| 	require.False(t, ethTxs[0].HasEmbeddedTx(testSDKAddress)) | ||||
| } | ||||
| 
 | ||||
| func TestGetEmbeddedTx(t *testing.T) { | ||||
| 	testCodec := newTestCodec() | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 
 | ||||
| 	ethTxs := newTestEthTxs( | ||||
| 		testChainID, | ||||
| 		[]*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]ethcmn.Address{testAddr1}, | ||||
| 	) | ||||
| 	sdkTxs := newTestSDKTxs( | ||||
| 		testCodec, testChainID, msgs, []*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]int64{0}, []int64{0}, newStdFee(), | ||||
| 	) | ||||
| 
 | ||||
| 	etx, err := sdkTxs[0].GetEmbeddedTx(testCodec) | ||||
| 	require.NoError(t, err) | ||||
| 	require.NotEmpty(t, etx.Messages) | ||||
| 
 | ||||
| 	etx, err = ethTxs[0].GetEmbeddedTx(testCodec) | ||||
| 	require.Error(t, err) | ||||
| 	require.Empty(t, etx.Messages) | ||||
| } | ||||
| 
 | ||||
| func TestTransactionGetMsgs(t *testing.T) { | ||||
| 	ethTxs := newTestEthTxs( | ||||
| 		testChainID, | ||||
| @ -246,7 +124,7 @@ func TestTransactionGetMsgs(t *testing.T) { | ||||
| 	require.Equal(t, ethTxs[0], msgs[0]) | ||||
| 
 | ||||
| 	expectedMsgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 	etx := newTestEmbeddedTx( | ||||
| 	etx := newTestStdTx( | ||||
| 		testChainID, expectedMsgs, []*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]int64{0}, []int64{0}, newStdFee(), | ||||
| 	) | ||||
| @ -256,21 +134,10 @@ func TestTransactionGetMsgs(t *testing.T) { | ||||
| 	require.Equal(t, expectedMsgs, msgs) | ||||
| } | ||||
| 
 | ||||
| func TestGetRequiredSigners(t *testing.T) { | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 	etx := newTestEmbeddedTx( | ||||
| 		testChainID, msgs, []*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]int64{0}, []int64{0}, newStdFee(), | ||||
| 	) | ||||
| 
 | ||||
| 	signers := etx.(EmbeddedTx).GetRequiredSigners() | ||||
| 	require.Equal(t, []sdk.AccAddress{sdk.AccAddress(testAddr1.Bytes())}, signers) | ||||
| } | ||||
| 
 | ||||
| func TestTxDecoder(t *testing.T) { | ||||
| 	testCodec := newTestCodec() | ||||
| 	txDecoder := TxDecoder(testCodec, testSDKAddress) | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 	txDecoder := TxDecoder(testCodec) | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg()} | ||||
| 
 | ||||
| 	// create a non-SDK Ethereum transaction
 | ||||
| 	emintTx := NewTransaction( | ||||
| @ -284,43 +151,20 @@ func TestTxDecoder(t *testing.T) { | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, emintTx, tx) | ||||
| 
 | ||||
| 	// create embedded transaction and encode
 | ||||
| 	etx := newTestEmbeddedTx( | ||||
| 	// create a SDK (auth.StdTx) transaction and encode
 | ||||
| 	stdTx := newTestStdTx( | ||||
| 		testChainID, msgs, []*ecdsa.PrivateKey{testPrivKey1}, | ||||
| 		[]int64{0}, []int64{0}, newStdFee(), | ||||
| 	) | ||||
| 
 | ||||
| 	payload := testCodec.MustMarshalBinary(etx) | ||||
| 
 | ||||
| 	expectedEtx := EmbeddedTx{} | ||||
| 	testCodec.UnmarshalBinary(payload, &expectedEtx) | ||||
| 
 | ||||
| 	emintTx = NewTransaction( | ||||
| 		uint64(0), testSDKAddress, sdk.NewInt(10), 100, | ||||
| 		sdk.NewInt(100), payload, | ||||
| 	) | ||||
| 	emintTx.Sign(testChainID, testPrivKey1) | ||||
| 
 | ||||
| 	// require the transaction to properly decode into a Transaction
 | ||||
| 	txBytes = testCodec.MustMarshalBinary(emintTx) | ||||
| 	txBytes = testCodec.MustMarshalBinary(stdTx) | ||||
| 	tx, err = txDecoder(txBytes) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, expectedEtx, tx) | ||||
| 	require.Equal(t, stdTx, tx) | ||||
| 
 | ||||
| 	// require the decoding to fail when no transaction bytes are given
 | ||||
| 	tx, err = txDecoder([]byte{}) | ||||
| 	require.Error(t, err) | ||||
| 	require.Nil(t, tx) | ||||
| 
 | ||||
| 	// create a non-SDK Ethereum transaction with an SDK address and garbage payload
 | ||||
| 	emintTx = NewTransaction( | ||||
| 		uint64(0), testSDKAddress, sdk.NewInt(10), 100, sdk.NewInt(100), []byte("garbage"), | ||||
| 	) | ||||
| 	emintTx.Sign(testChainID, testPrivKey1) | ||||
| 
 | ||||
| 	// require the transaction to fail decoding as the payload is invalid
 | ||||
| 	txBytes = testCodec.MustMarshalBinary(emintTx) | ||||
| 	tx, err = txDecoder(txBytes) | ||||
| 	require.Error(t, err) | ||||
| 	require.Nil(t, tx) | ||||
| } | ||||
|  | ||||
| @ -2,8 +2,11 @@ package types | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/sha256" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/cosmos/cosmos-sdk/x/auth" | ||||
| 	ethcmn "github.com/ethereum/go-ethereum/common" | ||||
| 	ethcrypto "github.com/ethereum/go-ethereum/crypto" | ||||
| 
 | ||||
| @ -39,3 +42,11 @@ func ValidateSigner(signBytes, sig []byte, signer ethcmn.Address) error { | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // GetStdTxSignBytes returns the signature bytes for an auth.StdTx transaction
 | ||||
| // that is compatible with Ethereum's signature mechanism.
 | ||||
| func GetStdTxSignBytes(chainID string, accNum int64, seq int64, fee auth.StdFee, msgs []sdk.Msg, memo string) []byte { | ||||
| 	signBytes := auth.StdSignBytes(chainID, accNum, seq, fee, msgs, "") | ||||
| 	hash := sha256.Sum256(signBytes) | ||||
| 	return hash[:] | ||||
| } | ||||
|  | ||||
| @ -12,12 +12,8 @@ import ( | ||||
| func TestValidateSigner(t *testing.T) { | ||||
| 	msgs := []sdk.Msg{sdk.NewTestMsg(sdk.AccAddress(testAddr1.Bytes()))} | ||||
| 
 | ||||
| 	// create message signing structure
 | ||||
| 	signEtx := EmbeddedTxSign{testChainID.String(), 0, 0, msgs, newStdFee()} | ||||
| 
 | ||||
| 	// create signing bytes and sign
 | ||||
| 	signBytes, err := signEtx.Bytes() | ||||
| 	require.NoError(t, err) | ||||
| 	// create message signing structure and bytes
 | ||||
| 	signBytes := GetStdTxSignBytes(testChainID.String(), 0, 0, newStdFee(), msgs, "") | ||||
| 
 | ||||
| 	// require signing not to fail
 | ||||
| 	sig, err := ethcrypto.Sign(signBytes, testPrivKey1) | ||||
|  | ||||
| @ -18,5 +18,4 @@ func RegisterWire(codec *wire.Codec) { | ||||
| 	codec.RegisterConcrete(&EthSignature{}, "types/EthSignature", nil) | ||||
| 	codec.RegisterConcrete(TxData{}, "types/TxData", nil) | ||||
| 	codec.RegisterConcrete(Transaction{}, "types/Transaction", nil) | ||||
| 	codec.RegisterConcrete(EmbeddedTx{}, "types/EmbeddedTx", nil) | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user