diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index 1b48c0e5f..5c7f7a19b 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -22,6 +22,7 @@ import ( "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/internal/utils" + staking "github.com/harmony-one/harmony/staking/types" ) // ReadTxLookupEntry retrieves the positional metadata associated with a transaction @@ -56,6 +57,20 @@ func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { utils.Logger().Error().Err(err).Msg("Failed to store transaction lookup entry") } } + for i, tx := range block.StakingTransactions() { + entry := TxLookupEntry{ + BlockHash: block.Hash(), + BlockIndex: block.NumberU64(), + Index: uint64(len(block.Transactions()) + i), + } + data, err := rlp.EncodeToBytes(entry) + if err != nil { + utils.Logger().Error().Err(err).Msg("Failed to encode staking transaction lookup entry") + } + if err := db.Put(txLookupKey(tx.Hash()), data); err != nil { + utils.Logger().Error().Err(err).Msg("Failed to store staking transaction lookup entry") + } + } } // DeleteTxLookupEntry removes all transaction data associated with a hash. @@ -91,6 +106,34 @@ func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, c return tx, blockHash, blockNumber, txIndex } +// ReadStakingTransaction retrieves a specific staking transaction from the database, along with +// its added positional metadata. +func ReadStakingTransaction(db DatabaseReader, hash common.Hash) (*staking.StakingTransaction, common.Hash, uint64, uint64) { + blockHash, blockNumber, txIndex := ReadTxLookupEntry(db, hash) + if blockHash == (common.Hash{}) { + return nil, common.Hash{}, 0, 0 + } + body := ReadBody(db, blockHash, blockNumber) + if body == nil { + utils.Logger().Error(). + Uint64("number", blockNumber). + Str("hash", blockHash.Hex()). + Uint64("index", txIndex). + Msg("block Body referenced missing") + return nil, common.Hash{}, 0, 0 + } + tx := body.StakingTransactionAt(int(txIndex)) + if tx == nil { + utils.Logger().Error(). + Uint64("number", blockNumber). + Str("hash", blockHash.Hex()). + Uint64("index", txIndex). + Msg("StakingTransaction referenced missing") + return nil, common.Hash{}, 0, 0 + } + return tx, blockHash, blockNumber, txIndex +} + // ReadReceipt retrieves a specific transaction receipt from the database, along with // its added positional metadata. func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { diff --git a/internal/hmyapi/transactionpool.go b/internal/hmyapi/transactionpool.go index 8f52f81f5..0ce5b0ef9 100644 --- a/internal/hmyapi/transactionpool.go +++ b/internal/hmyapi/transactionpool.go @@ -204,11 +204,54 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod return SubmitTransaction(ctx, s.b, tx) } +func (s *PublicTransactionPoolAPI) fillTransactionFields(tx *types.Transaction, fields map[string]interface{}) error { + var err error + fields["shardID"] = tx.ShardID() + var signer types.Signer = types.FrontierSigner{} + if tx.Protected() { + signer = types.NewEIP155Signer(tx.ChainID()) + } + from, _ := types.Sender(signer, tx) + fields["from"] = from + fields["to"] = "" + if tx.To() != nil { + fields["to"], err = internal_common.AddressToBech32(*tx.To()) + if err != nil { + return err + } + fields["from"], err = internal_common.AddressToBech32(from) + if err != nil { + return err + } + } + return nil +} + +func (s *PublicTransactionPoolAPI) fillStakingTransactionFields(stx *staking.StakingTransaction, fields map[string]interface{}) error { + from, err := stx.SenderAddress() + if err != nil { + return err + } + fields["sender"], err = internal_common.AddressToBech32(from) + if err != nil { + return err + } + fields["type"] = stx.StakingType() + return nil +} + // GetTransactionReceipt returns the transaction receipt for the given transaction hash. func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { - tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash) + var tx *types.Transaction + var stx *staking.StakingTransaction + var blockHash common.Hash + var blockNumber, index uint64 + tx, blockHash, blockNumber, index = rawdb.ReadTransaction(s.b.ChainDb(), hash) if tx == nil { - return nil, nil + stx, blockHash, blockNumber, index = rawdb.ReadStakingTransaction(s.b.ChainDb(), hash) + if stx == nil { + return nil, nil + } } receipts, err := s.b.GetReceipts(ctx, blockHash) if err != nil { @@ -218,33 +261,23 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha return nil, nil } receipt := receipts[index] - - var signer types.Signer = types.FrontierSigner{} - if tx.Protected() { - signer = types.NewEIP155Signer(tx.ChainID()) - } fields := map[string]interface{}{ "blockHash": blockHash, "blockNumber": hexutil.Uint64(blockNumber), "transactionHash": hash, "transactionIndex": hexutil.Uint64(index), - "shardID": tx.ShardID(), "gasUsed": hexutil.Uint64(receipt.GasUsed), "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), "contractAddress": nil, "logs": receipt.Logs, "logsBloom": receipt.Bloom, } - from, _ := types.Sender(signer, tx) - fields["from"] = from - fields["to"] = "" - if tx.To() != nil { - fields["to"], err = internal_common.AddressToBech32(*tx.To()) - if err != nil { + if tx != nil { + if err = s.fillTransactionFields(tx, fields); err != nil { return nil, err } - fields["from"], err = internal_common.AddressToBech32(from) - if err != nil { + } else { // stx not nil + if err = s.fillStakingTransactionFields(stx, fields); err != nil { return nil, err } }