MarshalBinary and UnmarshalBinary methods for receipt

This commit is contained in:
Ian Norden 2021-04-28 15:17:41 -05:00
parent 25302f3c30
commit b653dd7ce4

View File

@ -41,6 +41,9 @@ var (
// This error is returned when a typed receipt is decoded, but the string is empty.
var errEmptyTypedReceipt = errors.New("empty typed receipt bytes")
// This error is returned when a typed receipt has an unsupported type
var errRctTypeNotSupported = errors.New("receipt type not supported")
const (
// ReceiptStatusFailed is the status code of a transaction if execution failed.
ReceiptStatusFailed = uint64(0)
@ -155,6 +158,24 @@ func (r *Receipt) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, buf.Bytes())
}
// MarshalBinary returns the canonical encoding of the receipt.
// For legacy receipts, it returns the RLP encoding. For EIP-2718 typed
// receipts, it returns the type and payload.
func (r *Receipt) MarshalBinary() ([]byte, error) {
if r.Type == LegacyTxType {
return rlp.EncodeToBytes(r)
}
data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs}
buf := encodeBufferPool.Get().(*bytes.Buffer)
defer encodeBufferPool.Put(buf)
buf.Reset()
buf.WriteByte(r.Type)
if err := rlp.Encode(buf, data); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
// from an RLP stream.
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
@ -193,6 +214,42 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
}
}
// UnmarshalBinary decodes the canonical encoding of receipts.
// It supports legacy RLP receipts and EIP2718 typed receipts.
func (r *Receipt) UnmarshalBinary(b []byte) error {
if len(b) > 0 && b[0] > 0x7f {
// It's a legacy receipt decode the RLP
var data receiptRLP
err := rlp.DecodeBytes(b, &data)
if err != nil {
return err
}
r.Type = LegacyTxType
return r.setFromRLP(data)
}
// It's an EIP2718 typed transaction envelope.
return r.decodeTyped(b)
}
// decodeTyped decodes a typed receipt from the canonical format.
func (r *Receipt) decodeTyped(b []byte) error {
if len(b) == 0 {
return errEmptyTypedReceipt
}
switch b[0] {
case AccessListTxType:
var data receiptRLP
err := rlp.DecodeBytes(b[1:], &data)
if err != nil {
return err
}
r.Type = AccessListTxType
return r.setFromRLP(data)
default:
return ErrTxTypeNotSupported
}
}
func (r *Receipt) setFromRLP(data receiptRLP) error {
r.CumulativeGasUsed, r.Bloom, r.Logs = data.CumulativeGasUsed, data.Bloom, data.Logs
return r.setStatus(data.PostStateOrStatus)