diff --git a/core/blockchain.go b/core/blockchain.go index d6dad27991..91c494489a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -799,6 +799,11 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty // The transaction hash can be retrieved from the transaction itself receipts[j].TxHash = transactions[j].Hash() + // block location fields + receipts[j].BlockHash = block.Hash() + receipts[j].BlockNumber = block.Number() + receipts[j].TransactionIndex = big.NewInt(int64(j)) + // The contract address can be derived from the transaction itself if transactions[j].To() == nil { // Deriving the signer is expensive, only do if it's actually needed diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 8a95dafe95..e6eb54c1fc 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -306,6 +306,9 @@ func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Rece logIndex += 1 } receipts[i] = (*types.Receipt)(receipt) + receipts[i].BlockHash = hash + receipts[i].BlockNumber = big.NewInt(0).SetUint64(number) + receipts[i].TransactionIndex = big.NewInt(int64(i)) } return receipts } diff --git a/core/state/statedb.go b/core/state/statedb.go index 8ad25a5824..a934c8b4e7 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -221,6 +221,10 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 { return 0 } +func (self *StateDB) TxIndex() int { + return self.txIndex +} + func (self *StateDB) GetCode(addr common.Address) []byte { stateObject := self.getStateObject(addr) if stateObject != nil { diff --git a/core/state_processor.go b/core/state_processor.go index 503a35d16a..b23b5cda79 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "math/big" ) // StateProcessor is a basic Processor, which takes care of transitioning @@ -121,6 +122,9 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Set the receipt logs and create a bloom for filtering receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.BlockHash = header.Hash() + receipt.BlockNumber = header.Number + receipt.TransactionIndex = big.NewInt(int64(statedb.TxIndex())) return receipt, gas, err } diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go index 5c807a4ccb..495a78be93 100644 --- a/core/types/gen_receipt_json.go +++ b/core/types/gen_receipt_json.go @@ -5,6 +5,7 @@ package types import ( "encoding/json" "errors" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -23,6 +24,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex *hexutil.Big `json:"transactionIndex,omitempty"` } var enc Receipt enc.PostState = r.PostState @@ -33,6 +37,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { enc.TxHash = r.TxHash enc.ContractAddress = r.ContractAddress enc.GasUsed = hexutil.Uint64(r.GasUsed) + enc.BlockHash = r.BlockHash + enc.BlockNumber = (*hexutil.Big)(r.BlockNumber) + enc.TransactionIndex = (*hexutil.Big)(r.TransactionIndex) return json.Marshal(&enc) } @@ -47,6 +54,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { TxHash *common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress *common.Address `json:"contractAddress"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex *hexutil.Big `json:"transactionIndex,omitempty"` } var dec Receipt if err := json.Unmarshal(input, &dec); err != nil { @@ -81,5 +91,14 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'gasUsed' for Receipt") } r.GasUsed = uint64(*dec.GasUsed) + if dec.BlockHash != nil { + r.BlockHash = *dec.BlockHash + } + if dec.BlockNumber != nil { + r.BlockNumber = (*big.Int)(dec.BlockNumber) + } + if dec.TransactionIndex != nil { + r.TransactionIndex = (*big.Int)(dec.TransactionIndex) + } return nil } diff --git a/core/types/receipt.go b/core/types/receipt.go index ac1ebe349b..4beed41bee 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "io" + "math/big" "unsafe" "github.com/ethereum/go-ethereum/common" @@ -55,6 +56,11 @@ type Receipt struct { TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` + + // Block location fields - not part of the rlp + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *big.Int `json:"blockNumber,omitempty"` + TransactionIndex *big.Int `json:"transactionIndex,omitempty"` } type receiptMarshaling struct { @@ -62,6 +68,8 @@ type receiptMarshaling struct { Status hexutil.Uint64 CumulativeGasUsed hexutil.Uint64 GasUsed hexutil.Uint64 + BlockNumber *hexutil.Big + TransactionIndex *hexutil.Big } // receiptRLP is the consensus encoding of a receipt. diff --git a/miner/worker.go b/miner/worker.go index 48473796bc..240de31d7a 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -566,6 +566,11 @@ func (w *worker) resultLoop() { logs []*types.Log ) for i, receipt := range task.receipts { + // add block location fields + receipt.BlockHash = hash + receipt.BlockNumber = block.Number() + receipt.TransactionIndex = big.NewInt(int64(i)) + receipts[i] = new(types.Receipt) *receipts[i] = *receipt // Update the block hash in all logs since it is now available and not when the