feat: events: version the MessageReceipt structure. (#9636)
This commit is contained in:
parent
ae7847d097
commit
c75d0c4bd1
@ -344,12 +344,8 @@ func fakeReceipt(tb testing.TB, rng *pseudo.Rand, st adt.Store, events []*types.
|
|||||||
eventsRoot, err := arr.Root()
|
eventsRoot, err := arr.Root()
|
||||||
require.NoError(tb, err, "flush events amt")
|
require.NoError(tb, err, "flush events amt")
|
||||||
|
|
||||||
return &types.MessageReceipt{
|
rec := types.NewMessageReceiptV1(exitcode.Ok, randomBytes(32, rng), rng.Int63(), &eventsRoot)
|
||||||
ExitCode: exitcode.Ok,
|
return &rec
|
||||||
Return: randomBytes(32, rng),
|
|
||||||
GasUsed: rng.Int63(),
|
|
||||||
Events: eventsRoot,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeTipSet(tb testing.TB, rng *pseudo.Rand, h abi.ChainEpoch, parents []cid.Cid) *types.TipSet {
|
func fakeTipSet(tb testing.TB, rng *pseudo.Rand, h abi.ChainEpoch, parents []cid.Cid) *types.TipSet {
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
address "github.com/filecoin-project/go-address"
|
address "github.com/filecoin-project/go-address"
|
||||||
abi "github.com/filecoin-project/go-state-types/abi"
|
abi "github.com/filecoin-project/go-state-types/abi"
|
||||||
crypto "github.com/filecoin-project/go-state-types/crypto"
|
crypto "github.com/filecoin-project/go-state-types/crypto"
|
||||||
exitcode "github.com/filecoin-project/go-state-types/exitcode"
|
|
||||||
proof "github.com/filecoin-project/go-state-types/proof"
|
proof "github.com/filecoin-project/go-state-types/proof"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1289,189 +1288,6 @@ func (t *ActorV5) UnmarshalCBOR(r io.Reader) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var lengthBufMessageReceipt = []byte{132}
|
|
||||||
|
|
||||||
func (t *MessageReceipt) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cw := cbg.NewCborWriter(w)
|
|
||||||
|
|
||||||
if _, err := cw.Write(lengthBufMessageReceipt); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
|
||||||
if t.ExitCode >= 0 {
|
|
||||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Return ([]uint8) (slice)
|
|
||||||
if len(t.Return) > cbg.ByteArrayMaxLen {
|
|
||||||
return xerrors.Errorf("Byte array in field t.Return was too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := cw.Write(t.Return[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.GasUsed (int64) (int64)
|
|
||||||
if t.GasUsed >= 0 {
|
|
||||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.EventsRoot (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if t.EventsRoot == nil {
|
|
||||||
if _, err := cw.Write(cbg.CborNull); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cbg.WriteCid(cw, *t.EventsRoot); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.EventsRoot: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *MessageReceipt) UnmarshalCBOR(r io.Reader) (err error) {
|
|
||||||
*t = MessageReceipt{}
|
|
||||||
|
|
||||||
cr := cbg.NewCborReader(r)
|
|
||||||
|
|
||||||
maj, extra, err := cr.ReadHeader()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err == io.EOF {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 4 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
|
||||||
{
|
|
||||||
maj, extra, err := cr.ReadHeader()
|
|
||||||
var extraI int64
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch maj {
|
|
||||||
case cbg.MajUnsignedInt:
|
|
||||||
extraI = int64(extra)
|
|
||||||
if extraI < 0 {
|
|
||||||
return fmt.Errorf("int64 positive overflow")
|
|
||||||
}
|
|
||||||
case cbg.MajNegativeInt:
|
|
||||||
extraI = int64(extra)
|
|
||||||
if extraI < 0 {
|
|
||||||
return fmt.Errorf("int64 negative oveflow")
|
|
||||||
}
|
|
||||||
extraI = -1 - extraI
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.ExitCode = exitcode.ExitCode(extraI)
|
|
||||||
}
|
|
||||||
// t.Return ([]uint8) (slice)
|
|
||||||
|
|
||||||
maj, extra, err = cr.ReadHeader()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra > cbg.ByteArrayMaxLen {
|
|
||||||
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
|
||||||
}
|
|
||||||
if maj != cbg.MajByteString {
|
|
||||||
return fmt.Errorf("expected byte array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra > 0 {
|
|
||||||
t.Return = make([]uint8, extra)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// t.GasUsed (int64) (int64)
|
|
||||||
{
|
|
||||||
maj, extra, err := cr.ReadHeader()
|
|
||||||
var extraI int64
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch maj {
|
|
||||||
case cbg.MajUnsignedInt:
|
|
||||||
extraI = int64(extra)
|
|
||||||
if extraI < 0 {
|
|
||||||
return fmt.Errorf("int64 positive overflow")
|
|
||||||
}
|
|
||||||
case cbg.MajNegativeInt:
|
|
||||||
extraI = int64(extra)
|
|
||||||
if extraI < 0 {
|
|
||||||
return fmt.Errorf("int64 negative oveflow")
|
|
||||||
}
|
|
||||||
extraI = -1 - extraI
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.GasUsed = int64(extraI)
|
|
||||||
}
|
|
||||||
// t.EventsRoot (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
b, err := cr.ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if b != cbg.CborNull[0] {
|
|
||||||
if err := cr.UnreadByte(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(cr)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.EventsRoot: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.EventsRoot = &c
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var lengthBufBlockMsg = []byte{131}
|
var lengthBufBlockMsg = []byte{131}
|
||||||
|
|
||||||
func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
|
func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
|
||||||
|
@ -8,14 +8,52 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/exitcode"
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MessageReceiptVersion byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MessageReceiptV0 refers to pre FIP-0049 receipts.
|
||||||
|
MessageReceiptV0 MessageReceiptVersion = 0
|
||||||
|
// MessageReceiptV1 refers to post FIP-0049 receipts.
|
||||||
|
MessageReceiptV1 MessageReceiptVersion = 1
|
||||||
|
)
|
||||||
|
|
||||||
type MessageReceipt struct {
|
type MessageReceipt struct {
|
||||||
|
version MessageReceiptVersion
|
||||||
|
|
||||||
ExitCode exitcode.ExitCode
|
ExitCode exitcode.ExitCode
|
||||||
Return []byte
|
Return []byte
|
||||||
GasUsed int64
|
GasUsed int64
|
||||||
EventsRoot *cid.Cid // Root of Event AMT
|
EventsRoot *cid.Cid // Root of Event AMT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMessageReceiptV0 creates a new pre FIP-0049 receipt with no capability to
|
||||||
|
// convey events.
|
||||||
|
func NewMessageReceiptV0(exitcode exitcode.ExitCode, ret []byte, gasUsed int64) MessageReceipt {
|
||||||
|
return MessageReceipt{
|
||||||
|
version: MessageReceiptV0,
|
||||||
|
ExitCode: exitcode,
|
||||||
|
Return: ret,
|
||||||
|
GasUsed: gasUsed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMessageReceiptV1 creates a new pre FIP-0049 receipt with the ability to
|
||||||
|
// convey events.
|
||||||
|
func NewMessageReceiptV1(exitcode exitcode.ExitCode, ret []byte, gasUsed int64, eventsRoot *cid.Cid) MessageReceipt {
|
||||||
|
return MessageReceipt{
|
||||||
|
version: MessageReceiptV1,
|
||||||
|
ExitCode: exitcode,
|
||||||
|
Return: ret,
|
||||||
|
GasUsed: gasUsed,
|
||||||
|
EventsRoot: eventsRoot,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *MessageReceipt) Version() MessageReceiptVersion {
|
||||||
|
return mr.version
|
||||||
|
}
|
||||||
|
|
||||||
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
|
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
|
||||||
return mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && mr.GasUsed == o.GasUsed &&
|
return mr.version == mr.version && mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && mr.GasUsed == o.GasUsed &&
|
||||||
(mr.EventsRoot == o.EventsRoot || (mr.EventsRoot != nil && o.EventsRoot != nil && *mr.EventsRoot == *o.EventsRoot))
|
(mr.EventsRoot == o.EventsRoot || (mr.EventsRoot != nil && o.EventsRoot != nil && *mr.EventsRoot == *o.EventsRoot))
|
||||||
}
|
}
|
||||||
|
359
chain/types/message_receipt_cbor.go
Normal file
359
chain/types/message_receipt_cbor.go
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/cbor"
|
||||||
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file contains custom CBOR serde logic to deal with the new versioned
|
||||||
|
// MessageReceipt resulting from the introduction of actor events (FIP-0049).
|
||||||
|
|
||||||
|
type messageReceiptV0 struct{ *MessageReceipt }
|
||||||
|
|
||||||
|
type messageReceiptV1 struct{ *MessageReceipt }
|
||||||
|
|
||||||
|
func (mr *MessageReceipt) MarshalCBOR(w io.Writer) error {
|
||||||
|
if mr == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var m cbor.Marshaler
|
||||||
|
switch mr.version {
|
||||||
|
case MessageReceiptV0:
|
||||||
|
m = &messageReceiptV0{mr}
|
||||||
|
case MessageReceiptV1:
|
||||||
|
m = &messageReceiptV1{mr}
|
||||||
|
default:
|
||||||
|
return xerrors.Errorf("invalid message receipt version: %d", mr.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.MarshalCBOR(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *MessageReceipt) UnmarshalCBOR(r io.Reader) (err error) {
|
||||||
|
*mr = MessageReceipt{}
|
||||||
|
|
||||||
|
cr := cbg.NewCborReader(r)
|
||||||
|
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err == io.EOF {
|
||||||
|
err = io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if maj != cbg.MajArray {
|
||||||
|
return fmt.Errorf("cbor input should be of type array")
|
||||||
|
}
|
||||||
|
|
||||||
|
var u cbor.Unmarshaler
|
||||||
|
switch extra {
|
||||||
|
case 3:
|
||||||
|
mr.version = MessageReceiptV0
|
||||||
|
u = &messageReceiptV0{mr}
|
||||||
|
case 4:
|
||||||
|
mr.version = MessageReceiptV1
|
||||||
|
u = &messageReceiptV1{mr}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok to pass a CBOR reader since cbg.NewCborReader will return itself when
|
||||||
|
// already a CBOR reader.
|
||||||
|
return u.UnmarshalCBOR(cr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lengthBufAMessageReceiptV0 = []byte{131}
|
||||||
|
|
||||||
|
func (t *messageReceiptV0) MarshalCBOR(w io.Writer) error {
|
||||||
|
// eliding null check since nulls were already handled in the dispatcher
|
||||||
|
|
||||||
|
cw := cbg.NewCborWriter(w)
|
||||||
|
|
||||||
|
if _, err := cw.Write(lengthBufAMessageReceiptV0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||||
|
if t.ExitCode >= 0 {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.Return ([]uint8) (slice)
|
||||||
|
if len(t.Return) > cbg.ByteArrayMaxLen {
|
||||||
|
return xerrors.Errorf("Byte array in field t.Return was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := cw.Write(t.Return[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.GasUsed (int64) (int64)
|
||||||
|
if t.GasUsed >= 0 {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
|
||||||
|
cr := cbg.NewCborReader(r)
|
||||||
|
|
||||||
|
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||||
|
{
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ExitCode = exitcode.ExitCode(extraI)
|
||||||
|
}
|
||||||
|
// t.Return ([]uint8) (slice)
|
||||||
|
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > cbg.ByteArrayMaxLen {
|
||||||
|
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > 0 {
|
||||||
|
t.Return = make([]uint8, extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.GasUsed (int64) (int64)
|
||||||
|
{
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.GasUsed = extraI
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var lengthBufBMessageReceiptV1 = []byte{132}
|
||||||
|
|
||||||
|
func (t *messageReceiptV1) MarshalCBOR(w io.Writer) error {
|
||||||
|
// eliding null check since nulls were already handled in the dispatcher
|
||||||
|
|
||||||
|
cw := cbg.NewCborWriter(w)
|
||||||
|
|
||||||
|
if _, err := cw.Write(lengthBufBMessageReceiptV1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||||
|
if t.ExitCode >= 0 {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.Return ([]uint8) (slice)
|
||||||
|
if len(t.Return) > cbg.ByteArrayMaxLen {
|
||||||
|
return xerrors.Errorf("Byte array in field t.Return was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := cw.Write(t.Return[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.GasUsed (int64) (int64)
|
||||||
|
if t.GasUsed >= 0 {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.EventsRoot (cid.Cid) (struct)
|
||||||
|
|
||||||
|
if t.EventsRoot == nil {
|
||||||
|
if _, err := cw.Write(cbg.CborNull); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteCid(cw, *t.EventsRoot); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.EventsRoot: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
|
||||||
|
cr := cbg.NewCborReader(r)
|
||||||
|
|
||||||
|
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||||
|
{
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ExitCode = exitcode.ExitCode(extraI)
|
||||||
|
}
|
||||||
|
// t.Return ([]uint8) (slice)
|
||||||
|
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > cbg.ByteArrayMaxLen {
|
||||||
|
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
||||||
|
}
|
||||||
|
if maj != cbg.MajByteString {
|
||||||
|
return fmt.Errorf("expected byte array")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > 0 {
|
||||||
|
t.Return = make([]uint8, extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// t.GasUsed (int64) (int64)
|
||||||
|
{
|
||||||
|
maj, extra, err := cr.ReadHeader()
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.GasUsed = extraI
|
||||||
|
}
|
||||||
|
// t.EventsRoot (cid.Cid) (struct)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
b, err := cr.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b != cbg.CborNull[0] {
|
||||||
|
if err := cr.UnreadByte(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(cr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.EventsRoot: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.EventsRoot = &c
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
75
chain/types/message_receipt_test.go
Normal file
75
chain/types/message_receipt_test.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMessageReceiptSerdeRoundrip(t *testing.T) {
|
||||||
|
var (
|
||||||
|
assert = assert.New(t)
|
||||||
|
buf = new(bytes.Buffer)
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
randomCid, err := cid.Decode("bafy2bzacecu7n7wbtogznrtuuvf73dsz7wasgyneqasksdblxupnyovmtwxxu")
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version 0
|
||||||
|
//
|
||||||
|
mr := NewMessageReceiptV0(0, []byte{0x00, 0x01, 0x02, 0x04}, 42)
|
||||||
|
|
||||||
|
// marshal
|
||||||
|
err = mr.MarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
t.Logf("version 0: %s\n", hex.EncodeToString(buf.Bytes()))
|
||||||
|
|
||||||
|
// unmarshal
|
||||||
|
var mr2 MessageReceipt
|
||||||
|
err = mr2.UnmarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(mr, mr2)
|
||||||
|
|
||||||
|
// version 0 with an events root -- should not serialize the events root!
|
||||||
|
mr.EventsRoot = &randomCid
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
// marshal
|
||||||
|
err = mr.MarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
t.Logf("version 0 (with root): %s\n", hex.EncodeToString(buf.Bytes()))
|
||||||
|
|
||||||
|
// unmarshal
|
||||||
|
mr2 = MessageReceipt{}
|
||||||
|
err = mr2.UnmarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.NotEqual(mr, mr2)
|
||||||
|
assert.Nil(mr2.EventsRoot)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version 1
|
||||||
|
//
|
||||||
|
buf.Reset()
|
||||||
|
mr = NewMessageReceiptV1(0, []byte{0x00, 0x01, 0x02, 0x04}, 42, &randomCid)
|
||||||
|
|
||||||
|
// marshal
|
||||||
|
err = mr.MarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
t.Logf("version 1: %s\n", hex.EncodeToString(buf.Bytes()))
|
||||||
|
|
||||||
|
// unmarshal
|
||||||
|
mr2 = MessageReceipt{}
|
||||||
|
err = mr2.UnmarshalCBOR(buf)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(mr, mr2)
|
||||||
|
assert.NotNil(mr2.EventsRoot)
|
||||||
|
}
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||||
"github.com/filecoin-project/go-state-types/exitcode"
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
@ -275,6 +276,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add
|
|||||||
|
|
||||||
type FVM struct {
|
type FVM struct {
|
||||||
fvm *ffi.FVM
|
fvm *ffi.FVM
|
||||||
|
nv network.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
|
func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
|
||||||
@ -337,6 +339,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
|
|
||||||
return &FVM{
|
return &FVM{
|
||||||
fvm: fvm,
|
fvm: fvm,
|
||||||
|
nv: opts.NetworkVersion,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +442,7 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
|
|
||||||
return &FVM{
|
return &FVM{
|
||||||
fvm: fvm,
|
fvm: fvm,
|
||||||
|
nv: opts.NetworkVersion,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,10 +461,12 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
receipt := types.MessageReceipt{
|
|
||||||
Return: ret.Return,
|
var receipt types.MessageReceipt
|
||||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
if vm.nv >= network.Version18 {
|
||||||
GasUsed: ret.GasUsed,
|
receipt = types.NewMessageReceiptV1(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed, ret.EventsRoot)
|
||||||
|
} else {
|
||||||
|
receipt = types.NewMessageReceiptV0(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
var aerr aerrors.ActorError
|
var aerr aerrors.ActorError
|
||||||
@ -521,10 +527,12 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
receipt := types.MessageReceipt{
|
|
||||||
Return: ret.Return,
|
var receipt types.MessageReceipt
|
||||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
if vm.nv >= network.Version18 {
|
||||||
GasUsed: ret.GasUsed,
|
receipt = types.NewMessageReceiptV1(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed, ret.EventsRoot)
|
||||||
|
} else {
|
||||||
|
receipt = types.NewMessageReceiptV0(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
var aerr aerrors.ActorError
|
var aerr aerrors.ActorError
|
||||||
|
@ -28,7 +28,7 @@ func main() {
|
|||||||
types.MsgMeta{},
|
types.MsgMeta{},
|
||||||
types.ActorV4{},
|
types.ActorV4{},
|
||||||
types.ActorV5{},
|
types.ActorV5{},
|
||||||
types.MessageReceipt{},
|
// types.MessageReceipt{}, // Custom serde to deal with versioning.
|
||||||
types.BlockMsg{},
|
types.BlockMsg{},
|
||||||
types.ExpTipSet{},
|
types.ExpTipSet{},
|
||||||
types.BeaconEntry{},
|
types.BeaconEntry{},
|
||||||
|
Loading…
Reference in New Issue
Block a user