aboutsummaryrefslogtreecommitdiffstats
path: root/core/types/receipt.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2019-04-15 17:36:27 +0800
committerPéter Szilágyi <peterke@gmail.com>2019-04-15 18:42:26 +0800
commit7221cb1434eebce879a0bd1bf3867cd8a24bcc99 (patch)
tree364dc21a521f89da13c69990238e13afeda3e6c1 /core/types/receipt.go
parent6b0ddd141e2e12bb09b33e14e67aed4d5a68d66c (diff)
downloadgo-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar.gz
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar.bz2
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar.lz
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar.xz
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.tar.zst
go-tangerine-7221cb1434eebce879a0bd1bf3867cd8a24bcc99.zip
core, eth, les, light: scope receipt functionality a bit cleaner
Diffstat (limited to 'core/types/receipt.go')
-rw-r--r--core/types/receipt.go72
1 files changed, 56 insertions, 16 deletions
diff --git a/core/types/receipt.go b/core/types/receipt.go
index dc8177079..578daba3f 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -18,6 +18,7 @@ package types
import (
"bytes"
+ "errors"
"fmt"
"io"
"math/big"
@@ -25,6 +26,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -99,8 +102,8 @@ type v4StoredReceiptRLP struct {
GasUsed uint64
}
-// legacyStoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
-type legacyStoredReceiptRLP struct {
+// v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
+type v3StoredReceiptRLP struct {
PostStateOrStatus []byte
CumulativeGasUsed uint64
Bloom Bloom
@@ -198,20 +201,21 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
// fields of a receipt from an RLP stream.
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
+ // Retrieve the entire receipt blob as we need to try multiple decoders
blob, err := s.Raw()
if err != nil {
return err
}
-
+ // Try decoding from the newest format for future proofness, then the older one
+ // for old nodes that just upgraded. V4 was an intermediate unreleased format so
+ // we do need to decode it, but it's not common (try last).
if err := decodeStoredReceiptRLP(r, blob); err == nil {
return nil
}
-
- if err := decodeV4StoredReceiptRLP(r, blob); err == nil {
+ if err := decodeV3StoredReceiptRLP(r, blob); err == nil {
return nil
}
-
- return decodeLegacyStoredReceiptRLP(r, blob)
+ return decodeV4StoredReceiptRLP(r, blob)
}
func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
@@ -219,11 +223,9 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
if err := rlp.DecodeBytes(blob, &stored); err != nil {
return err
}
-
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
return err
}
-
r.CumulativeGasUsed = stored.CumulativeGasUsed
r.Logs = make([]*Log, len(stored.Logs))
for i, log := range stored.Logs {
@@ -239,11 +241,9 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
if err := rlp.DecodeBytes(blob, &stored); err != nil {
return err
}
-
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
return err
}
-
r.CumulativeGasUsed = stored.CumulativeGasUsed
r.TxHash = stored.TxHash
r.ContractAddress = stored.ContractAddress
@@ -257,16 +257,14 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
return nil
}
-func decodeLegacyStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
- var stored legacyStoredReceiptRLP
+func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
+ var stored v3StoredReceiptRLP
if err := rlp.DecodeBytes(blob, &stored); err != nil {
return err
}
-
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
return err
}
-
r.CumulativeGasUsed = stored.GasUsed
r.Bloom = stored.Bloom
r.TxHash = stored.TxHash
@@ -276,7 +274,6 @@ func decodeLegacyStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
for i, log := range stored.Logs {
r.Logs[i] = (*Log)(log)
}
-
return nil
}
@@ -294,3 +291,46 @@ func (r Receipts) GetRlp(i int) []byte {
}
return bytes
}
+
+// DeriveFields fills the receipts with their computed fields based on consensus
+// data and contextual infos like containing block and transactions.
+func (r Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, txs Transactions) error {
+ signer := MakeSigner(config, new(big.Int).SetUint64(number))
+
+ logIndex := uint(0)
+ if len(txs) != len(r) {
+ return errors.New("transaction and receipt count mismatch")
+ }
+ for i := 0; i < len(r); i++ {
+ // The transaction hash can be retrieved from the transaction itself
+ r[i].TxHash = txs[i].Hash()
+
+ // block location fields
+ r[i].BlockHash = hash
+ r[i].BlockNumber = new(big.Int).SetUint64(number)
+ r[i].TransactionIndex = uint(i)
+
+ // The contract address can be derived from the transaction itself
+ if txs[i].To() == nil {
+ // Deriving the signer is expensive, only do if it's actually needed
+ from, _ := Sender(signer, txs[i])
+ r[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce())
+ }
+ // The used gas can be calculated based on previous r
+ if i == 0 {
+ r[i].GasUsed = r[i].CumulativeGasUsed
+ } else {
+ r[i].GasUsed = r[i].CumulativeGasUsed - r[i-1].CumulativeGasUsed
+ }
+ // The derived log fields can simply be set from the block and transaction
+ for j := 0; j < len(r[i].Logs); j++ {
+ r[i].Logs[j].BlockNumber = number
+ r[i].Logs[j].BlockHash = hash
+ r[i].Logs[j].TxHash = r[i].TxHash
+ r[i].Logs[j].TxIndex = uint(i)
+ r[i].Logs[j].Index = logIndex
+ logIndex++
+ }
+ }
+ return nil
+}