core: minor polishes to the Metropolis EIP 98 implementation

This commit is contained in:
Péter Szilágyi 2017-07-04 13:43:03 +03:00
parent fed5871aa9
commit a301c75029
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
2 changed files with 31 additions and 10 deletions

View file

@ -104,13 +104,14 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
} }
// Update the state with pending changes // Update the state with pending changes
usedGas.Add(usedGas, gas)
var root []byte var root []byte
if config.IsMetropolis(header.Number) { if config.IsMetropolis(header.Number) {
statedb.Finalise() statedb.Finalise()
} else { } else {
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
} }
usedGas.Add(usedGas, gas)
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx // Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
// based on the eip phase, we're passing wether the root touch-delete accounts. // based on the eip phase, we're passing wether the root touch-delete accounts.
receipt := types.NewReceipt(root, usedGas) receipt := types.NewReceipt(root, usedGas)

View file

@ -48,6 +48,8 @@ type receiptMarshaling struct {
GasUsed *hexutil.Big GasUsed *hexutil.Big
} }
// homesteadReceiptRLP contains the receipt's Homestead consensus fields, used
// during RLP serialization.
type homesteadReceiptRLP struct { type homesteadReceiptRLP struct {
PostState []byte PostState []byte
CumulativeGasUsed *big.Int CumulativeGasUsed *big.Int
@ -55,6 +57,8 @@ type homesteadReceiptRLP struct {
Logs []*Log Logs []*Log
} }
// metropolisReceiptRLP contains the receipt's Metropolis consensus fields, used
// during RLP serialization.
type metropolisReceiptRLP struct { type metropolisReceiptRLP struct {
CumulativeGasUsed *big.Int CumulativeGasUsed *big.Int
Bloom Bloom Bloom Bloom
@ -67,34 +71,50 @@ func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt {
} }
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
// into an RLP stream. // into an RLP stream. If no post state is present, metropolis fork is assumed.
func (r *Receipt) EncodeRLP(w io.Writer) error { func (r *Receipt) EncodeRLP(w io.Writer) error {
if r.PostState == nil { if r.PostState == nil {
return rlp.Encode(w, &metropolisReceiptRLP{r.CumulativeGasUsed, r.Bloom, r.Logs}) return rlp.Encode(w, &metropolisReceiptRLP{r.CumulativeGasUsed, r.Bloom, r.Logs})
} else {
return rlp.Encode(w, &homesteadReceiptRLP{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs})
} }
return rlp.Encode(w, &homesteadReceiptRLP{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs})
} }
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
// from an RLP stream. // from an RLP stream.
func (r *Receipt) DecodeRLP(s *rlp.Stream) error { func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
// Load the raw bytes since we have multiple possible formats
raw, err := s.Raw() raw, err := s.Raw()
if err != nil { if err != nil {
return err return err
} }
var hr homesteadReceiptRLP // Attempt to deserialize into a Metropolis format
var mr metropolisReceiptRLP var metro metropolisReceiptRLP
if err = rlp.DecodeBytes(raw, &mr); err == nil { if err = rlp.DecodeBytes(raw, &metro); err == nil { // Keep the error in the outer scope!
r.CumulativeGasUsed, r.Bloom, r.Logs = mr.CumulativeGasUsed, mr.Bloom, mr.Logs r.CumulativeGasUsed = metro.CumulativeGasUsed
} else if err = rlp.DecodeBytes(raw, &hr); err == nil { r.Bloom = metro.Bloom
r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs = hr.PostState[:], hr.CumulativeGasUsed, hr.Bloom, hr.Logs r.Logs = metro.Logs
return nil
} }
// Metropolis deserialization failed, attempt homestead
var home homesteadReceiptRLP
if err = rlp.DecodeBytes(raw, &home); err == nil { // Keep the error in the outer scope!
r.PostState = home.PostState[:]
r.CumulativeGasUsed = home.CumulativeGasUsed
r.Bloom = home.Bloom
r.Logs = home.Logs
return nil
}
// All decoders failed, return the last error
return err return err
} }
// String implements the Stringer interface. // String implements the Stringer interface.
func (r *Receipt) String() string { func (r *Receipt) String() string {
if r.PostState == nil {
return fmt.Sprintf("receipt{cgas=%v bloom=%x logs=%v}", r.CumulativeGasUsed, r.Bloom, r.Logs)
}
return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs) return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs)
} }