imp: clean up the block fetch logic in json-rpc (#1081)

* clean up the block fetch logic in json-rpc

deduplicate some codes

fix EthBlockFromTm

fix latest block height

* add bug fix changelog
This commit is contained in:
yihuang 2022-05-24 00:36:31 +08:00 committed by GitHub
parent 2cfa8730c9
commit f06df8c265
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 214 deletions

View File

@ -38,6 +38,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
## Unreleased ## Unreleased
### API Breaking
- (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) Deduplicate some json-rpc logic codes, cleanup several dead functions.
### Improvements ### Improvements
* (cli) [tharsis#1086](https://github.com/tharsis/ethermint/pull/1086) Add rollback command. * (cli) [tharsis#1086](https://github.com/tharsis/ethermint/pull/1086) Add rollback command.
@ -46,6 +50,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [tharsis#1082](https://github.com/tharsis/ethermint/pull/1082) fix gas price returned in getTransaction api. * (rpc) [tharsis#1082](https://github.com/tharsis/ethermint/pull/1082) fix gas price returned in getTransaction api.
* (evm) [tharsis#1088](https://github.com/tharsis/ethermint/pull/1088) Fix ability to append log in tx post processing. * (evm) [tharsis#1088](https://github.com/tharsis/ethermint/pull/1088) Fix ability to append log in tx post processing.
* (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
## [v0.15.0] - 2022-05-09 ## [v0.15.0] - 2022-05-09

View File

@ -20,7 +20,6 @@ import (
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -71,7 +70,7 @@ func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map
return nil, nil return nil, nil
} }
res, err := b.EthBlockFromTendermint(resBlock.Block, fullTx) res, err := b.EthBlockFromTendermint(resBlock, fullTx)
if err != nil { if err != nil {
b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error())
return nil, err return nil, err
@ -82,61 +81,36 @@ func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map
// GetBlockByHash returns the block identified by hash. // GetBlockByHash returns the block identified by hash.
func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) resBlock, err := b.GetTendermintBlockByHash(hash)
if err != nil { if err != nil {
b.logger.Debug("BlockByHash block not found", "hash", hash.Hex(), "error", err.Error())
return nil, err return nil, err
} }
if resBlock == nil {
if resBlock == nil || resBlock.Block == nil { // block not found
b.logger.Debug("BlockByHash block not found", "hash", hash.Hex())
return nil, nil return nil, nil
} }
return b.EthBlockFromTendermint(resBlock.Block, fullTx) return b.EthBlockFromTendermint(resBlock, fullTx)
} }
// BlockByNumber returns the block identified by number. // BlockByNumber returns the block identified by number.
func (b *Backend) BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) { func (b *Backend) BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error) {
height := blockNum.Int64() resBlock, err := b.GetTendermintBlockByNumber(blockNum)
switch blockNum {
case types.EthLatestBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthPendingBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthEarliestBlockNumber:
height = 1
default:
if blockNum < 0 {
return nil, errors.Errorf("incorrect block height: %d", height)
}
}
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height)
if err != nil { if err != nil {
b.logger.Debug("HeaderByNumber failed", "height", height)
return nil, err return nil, err
} }
if resBlock == nil {
if resBlock == nil || resBlock.Block == nil { // block not found
return nil, errors.Errorf("block not found for height %d", height) return nil, errors.Errorf("block not found for height %d", blockNum)
} }
return b.EthBlockFromTm(resBlock.Block) return b.EthBlockFromTm(resBlock)
} }
// BlockByHash returns the block identified by hash. // BlockByHash returns the block identified by hash.
func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) { func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) {
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) resBlock, err := b.GetTendermintBlockByHash(hash)
if err != nil { if err != nil {
b.logger.Debug("HeaderByHash failed", "hash", hash.Hex())
return nil, err return nil, err
} }
@ -144,10 +118,11 @@ func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) {
return nil, errors.Errorf("block not found for hash %s", hash) return nil, errors.Errorf("block not found for hash %s", hash)
} }
return b.EthBlockFromTm(resBlock.Block) return b.EthBlockFromTm(resBlock)
} }
func (b *Backend) EthBlockFromTm(block *tmtypes.Block) (*ethtypes.Block, error) { func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock) (*ethtypes.Block, error) {
block := resBlock.Block
height := block.Height height := block.Height
bloom, err := b.BlockBloom(&height) bloom, err := b.BlockBloom(&height)
if err != nil { if err != nil {
@ -162,23 +137,16 @@ func (b *Backend) EthBlockFromTm(block *tmtypes.Block) (*ethtypes.Block, error)
ethHeader := types.EthHeaderFromTendermint(block.Header, bloom, baseFee) ethHeader := types.EthHeaderFromTendermint(block.Header, bloom, baseFee)
var txs []*ethtypes.Transaction resBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Height)
for _, txBz := range block.Txs { if err != nil {
tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) return nil, err
if err != nil { }
b.logger.Debug("failed to decode transaction in block", "height", height, "error", err.Error())
continue
}
for _, msg := range tx.GetMsgs() { msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, resBlockResult)
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
continue
}
tx := ethMsg.AsTransaction() txs := make([]*ethtypes.Transaction, len(msgs))
txs = append(txs, tx) for i, ethMsg := range msgs {
} txs[i] = ethMsg.AsTransaction()
} }
// TODO: add tx receipts // TODO: add tx receipts
@ -189,38 +157,22 @@ func (b *Backend) EthBlockFromTm(block *tmtypes.Block) (*ethtypes.Block, error)
// GetTendermintBlockByNumber returns a Tendermint format block by block number // GetTendermintBlockByNumber returns a Tendermint format block by block number
func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) { func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) {
height := blockNum.Int64() height := blockNum.Int64()
currentBlockNumber, _ := b.BlockNumber() if height <= 0 {
// fetch the latest block number from the app state, more accurate than the tendermint block store state.
switch blockNum { n, err := b.BlockNumber()
case types.EthLatestBlockNumber: if err != nil {
if currentBlockNumber > 0 { return nil, err
height = int64(currentBlockNumber)
}
case types.EthPendingBlockNumber:
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthEarliestBlockNumber:
height = 1
default:
if blockNum < 0 {
return nil, errors.Errorf("cannot fetch a negative block height: %d", height)
}
if height > int64(currentBlockNumber) {
return nil, nil
} }
height = int64(n)
} }
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height) resBlock, err := b.clientCtx.Client.Block(b.ctx, &height)
if err != nil { if err != nil {
if resBlock, err = b.clientCtx.Client.Block(b.ctx, nil); err != nil { b.logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error())
b.logger.Debug("tendermint client failed to get latest block", "height", height, "error", err.Error()) return nil, err
return nil, nil
}
} }
if resBlock.Block == nil { if resBlock.Block == nil {
b.logger.Debug("GetBlockByNumber block not found", "height", height) b.logger.Debug("GetTendermintBlockByNumber block not found", "height", height)
return nil, nil return nil, nil
} }
@ -232,10 +184,11 @@ func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.R
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes()) resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes())
if err != nil { if err != nil {
b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error())
return nil, err
} }
if resBlock == nil || resBlock.Block == nil { if resBlock == nil || resBlock.Block == nil {
b.logger.Debug("GetBlockByNumber block not found", "blockHash", blockHash.Hex()) b.logger.Debug("GetTendermintBlockByHash block not found", "blockHash", blockHash.Hex())
return nil, nil return nil, nil
} }
@ -264,67 +217,43 @@ func (b *Backend) BlockBloom(height *int64) (ethtypes.Bloom, error) {
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result. // EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result.
func (b *Backend) EthBlockFromTendermint( func (b *Backend) EthBlockFromTendermint(
block *tmtypes.Block, resBlock *tmrpctypes.ResultBlock,
fullTx bool, fullTx bool,
) (map[string]interface{}, error) { ) (map[string]interface{}, error) {
ethRPCTxs := []interface{}{} ethRPCTxs := []interface{}{}
block := resBlock.Block
ctx := types.ContextWithHeight(block.Height)
baseFee, err := b.BaseFee(block.Height) baseFee, err := b.BaseFee(block.Height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resBlockResult, err := b.clientCtx.Client.BlockResults(ctx, &block.Height) resBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
txResults := resBlockResult.TxsResults msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, resBlockResult)
txIndex := uint64(0) for txIndex, ethMsg := range msgs {
if !fullTx {
for i, txBz := range block.Txs { hash := common.HexToHash(ethMsg.Hash)
tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz) ethRPCTxs = append(ethRPCTxs, hash)
if err != nil {
b.logger.Debug("failed to decode transaction in block", "height", block.Height, "error", err.Error())
continue continue
} }
for _, msg := range tx.GetMsgs() { tx := ethMsg.AsTransaction()
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) rpcTx, err := types.NewRPCTransaction(
if !ok { tx,
continue common.BytesToHash(block.Hash()),
} uint64(block.Height),
uint64(txIndex),
tx := ethMsg.AsTransaction() baseFee,
)
// check tx exists on EVM by cross checking with blockResults if err != nil {
if txResults[i].Code != 0 { b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
b.logger.Debug("invalid tx result code", "hash", tx.Hash().Hex()) continue
continue
}
if !fullTx {
hash := tx.Hash()
ethRPCTxs = append(ethRPCTxs, hash)
continue
}
rpcTx, err := types.NewRPCTransaction(
tx,
common.BytesToHash(block.Hash()),
uint64(block.Height),
txIndex,
baseFee,
)
if err != nil {
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
continue
}
ethRPCTxs = append(ethRPCTxs, rpcTx)
txIndex++
} }
ethRPCTxs = append(ethRPCTxs, rpcTx)
} }
bloom, err := b.BlockBloom(&block.Height) bloom, err := b.BlockBloom(&block.Height)
@ -336,6 +265,7 @@ func (b *Backend) EthBlockFromTendermint(
ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(), ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(),
} }
ctx := types.ContextWithHeight(block.Height)
res, err := b.queryClient.ValidatorAccount(ctx, req) res, err := b.queryClient.ValidatorAccount(ctx, req)
if err != nil { if err != nil {
b.logger.Debug( b.logger.Debug(
@ -361,10 +291,10 @@ func (b *Backend) EthBlockFromTendermint(
gasUsed := uint64(0) gasUsed := uint64(0)
for _, txsResult := range txResults { for _, txsResult := range resBlockResult.TxsResults {
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832 // workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
if txsResult.GetCode() == 11 && txsResult.GetLog() == "no block gas left to run tx: out of gas" { if txsResult.GetCode() == 11 && txsResult.GetLog() == "no block gas left to run tx: out of gas" {
// block gas limit has exceeded, other txs must have failed with same reason. // block gas limit has exceeded, other txs must have failed for the same reason.
break break
} }
gasUsed += uint64(txsResult.GetGasUsed()) gasUsed += uint64(txsResult.GetGasUsed())
@ -386,31 +316,13 @@ func (b *Backend) CurrentHeader() *ethtypes.Header {
// HeaderByNumber returns the block header identified by height. // HeaderByNumber returns the block header identified by height.
func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) { func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) {
height := blockNum.Int64() resBlock, err := b.GetTendermintBlockByNumber(blockNum)
if err != nil {
switch blockNum { return nil, err
case types.EthLatestBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthPendingBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthEarliestBlockNumber:
height = 1
default:
if blockNum < 0 {
return nil, errors.Errorf("incorrect block height: %d", height)
}
} }
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height) if resBlock == nil {
if err != nil { return nil, errors.Errorf("block not found for height %d", blockNum)
b.logger.Debug("HeaderByNumber failed")
return nil, err
} }
bloom, err := b.BlockBloom(&resBlock.Block.Height) bloom, err := b.BlockBloom(&resBlock.Block.Height)
@ -430,13 +342,11 @@ func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header,
// HeaderByHash returns the block header identified by hash. // HeaderByHash returns the block header identified by hash.
func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) {
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes()) resBlock, err := b.GetTendermintBlockByHash(blockHash)
if err != nil { if err != nil {
b.logger.Debug("HeaderByHash failed", "hash", blockHash.Hex())
return nil, err return nil, err
} }
if resBlock == nil {
if resBlock == nil || resBlock.Block == nil {
return nil, errors.Errorf("block not found for hash %s", blockHash.Hex()) return nil, errors.Errorf("block not found for hash %s", blockHash.Hex())
} }
@ -498,36 +408,15 @@ func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) {
// GetLogs returns all the logs from all the ethereum transactions in a block. // GetLogs returns all the logs from all the ethereum transactions in a block.
func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) {
block, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) resBlock, err := b.GetTendermintBlockByHash(hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return b.GetLogsByHeight(&block.Block.Header.Height) if resBlock == nil {
} return nil, errors.Errorf("block not found for hash %s", hash)
func (b *Backend) GetLogsByNumber(blockNum types.BlockNumber) ([][]*ethtypes.Log, error) {
height := blockNum.Int64()
switch blockNum {
case types.EthLatestBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthPendingBlockNumber:
currentBlockNumber, _ := b.BlockNumber()
if currentBlockNumber > 0 {
height = int64(currentBlockNumber)
}
case types.EthEarliestBlockNumber:
height = 1
default:
if blockNum < 0 {
return nil, errors.Errorf("incorrect block height: %d", height)
}
} }
return b.GetLogsByHeight(&height) return b.GetLogsByHeight(&resBlock.Block.Header.Height)
} }
// BloomStatus returns the BloomBitsBlocks and the number of processed sections maintained // BloomStatus returns the BloomBitsBlocks and the number of processed sections maintained

View File

@ -342,7 +342,7 @@ func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Ui
// GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number.
func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint {
e.logger.Debug("eth_getBlockTransactionCountByNumber", "height", blockNum.Int64()) e.logger.Debug("eth_getBlockTransactionCountByNumber", "height", blockNum.Int64())
block, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight()) block, err := e.backend.GetTendermintBlockByNumber(blockNum)
if err != nil { if err != nil {
e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error())
return nil return nil
@ -800,7 +800,7 @@ func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexu
func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
block, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight()) block, err := e.backend.GetTendermintBlockByNumber(blockNum)
if err != nil { if err != nil {
e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error())
return nil, nil return nil, nil

View File

@ -29,7 +29,7 @@ type Backend interface {
HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error)
HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error)
GetLogsByNumber(blockNum types.BlockNumber) ([][]*ethtypes.Log, error) GetLogsByHeight(*int64) ([][]*ethtypes.Log, error)
BlockBloom(height *int64) (ethtypes.Bloom, error) BlockBloom(height *int64) (ethtypes.Bloom, error)
BloomStatus() (uint64, uint64) BloomStatus() (uint64, uint64)

View File

@ -172,7 +172,7 @@ func (f *Filter) blockLogs(height int64, bloom ethtypes.Bloom) ([]*ethtypes.Log,
// DANGER: do not call GetLogs(header.Hash()) // DANGER: do not call GetLogs(header.Hash())
// eth header's hash doesn't match tm block hash // eth header's hash doesn't match tm block hash
logsList, err := f.backend.GetLogsByNumber(types.BlockNumber(height)) logsList, err := f.backend.GetLogsByHeight(&height)
if err != nil { if err != nil {
return []*ethtypes.Log{}, errors.Wrapf(err, "failed to fetch logs block number %d", height) return []*ethtypes.Log{}, errors.Wrapf(err, "failed to fetch logs block number %d", height)
} }

View File

@ -3,7 +3,6 @@ package types
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/hex"
"fmt" "fmt"
"math/big" "math/big"
"strconv" "strconv"
@ -132,37 +131,6 @@ func FormatBlock(
return result return result
} }
type DataError interface {
Error() string // returns the message
ErrorData() interface{} // returns the error data
}
type dataError struct {
msg string
data string
}
func (d *dataError) Error() string {
return d.msg
}
func (d *dataError) ErrorData() interface{} {
return d.data
}
type SDKTxLogs struct {
Log string `json:"log"`
}
const LogRevertedFlag = "transaction reverted"
func ErrRevertedWith(data []byte) DataError {
return &dataError{
msg: "VM execution error.",
data: fmt.Sprintf("0x%s", hex.EncodeToString(data)),
}
}
// NewTransactionFromMsg returns a transaction that will serialize to the RPC // NewTransactionFromMsg returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available). // representation, with the given location metadata set (if available).
func NewTransactionFromMsg( func NewTransactionFromMsg(