Merge branch 'feat/nv18-fevm' into feat/nv18-events

This commit is contained in:
Raúl Kripalani 2022-11-15 12:28:25 +00:00
commit 846aea57c5
13 changed files with 278 additions and 46 deletions

View File

@ -916,6 +916,11 @@ workflows:
suite: itest-dup_mpool_messages
target: "./itests/dup_mpool_messages_test.go"
- test:
name: test-itest-fevm
suite: itest-fevm
target: "./itests/fevm_test.go"
- test:
name: test-itest-gas_estimation
suite: itest-gas_estimation

View File

@ -372,7 +372,7 @@ func init() {
addExample(&ethint)
ethaddr, _ := api.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031")
addExample(&ethaddr)
ethhash, _ := api.EthHashFromCid(c)
ethhash, _ := api.NewEthHashFromCid(c)
addExample(&ethhash)
ethFeeHistoryReward := [][]api.EthBigInt{}

View File

@ -37,7 +37,6 @@ type EthTx struct {
Type EthUint64 `json:"type"`
Input EthBytes `json:"input"`
Gas EthUint64 `json:"gas"`
GasLimit *EthUint64 `json:"gasLimit,omitempty"`
MaxFeePerGas EthBigInt `json:"maxFeePerGas"`
MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"`
V EthBytes `json:"v"`

View File

@ -110,6 +110,7 @@ func (e *EthBytes) UnmarshalJSON(b []byte) error {
}
type EthBlock struct {
Hash EthHash `json:"hash"`
ParentHash EthHash `json:"parentHash"`
Sha3Uncles EthHash `json:"sha3Uncles"`
Miner EthAddress `json:"miner"`
@ -117,16 +118,17 @@ type EthBlock struct {
TransactionsRoot EthHash `json:"transactionsRoot"`
ReceiptsRoot EthHash `json:"receiptsRoot"`
// TODO: include LogsBloom
Difficulty EthUint64 `json:"difficulty"`
Number EthUint64 `json:"number"`
GasLimit EthUint64 `json:"gasLimit"`
GasUsed EthUint64 `json:"gasUsed"`
Timestamp EthUint64 `json:"timestamp"`
Extradata []byte `json:"extraData"`
MixHash EthHash `json:"mixHash"`
Nonce EthNonce `json:"nonce"`
BaseFeePerGas EthBigInt `json:"baseFeePerGas"`
Size EthUint64 `json:"size"`
Difficulty EthUint64 `json:"difficulty"`
TotalDifficulty EthUint64 `json:"totalDifficulty"`
Number EthUint64 `json:"number"`
GasLimit EthUint64 `json:"gasLimit"`
GasUsed EthUint64 `json:"gasUsed"`
Timestamp EthUint64 `json:"timestamp"`
Extradata []byte `json:"extraData"`
MixHash EthHash `json:"mixHash"`
Nonce EthNonce `json:"nonce"`
BaseFeePerGas EthBigInt `json:"baseFeePerGas"`
Size EthUint64 `json:"size"`
// can be []EthTx or []string depending on query params
Transactions []interface{} `json:"transactions"`
Uncles []EthHash `json:"uncles"`
@ -406,7 +408,7 @@ func decodeHexString(s string, length int) ([]byte, error) {
return b, nil
}
func EthHashFromCid(c cid.Cid) (EthHash, error) {
func NewEthHashFromCid(c cid.Cid) (EthHash, error) {
return EthHashFromHex(c.Hash().HexString()[8:])
}

View File

@ -91,7 +91,7 @@ func TestEthHash(t *testing.T) {
require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1))
c := h.ToCid()
h1, err := EthHashFromCid(c)
h1, err := NewEthHashFromCid(c)
require.Nil(t, err)
require.Equal(t, h, h1)
}

View File

@ -7,6 +7,8 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
)
func TestEncode(t *testing.T) {
@ -175,16 +177,14 @@ func TestDecodeError(t *testing.T) {
}
func TestDecode1(t *testing.T) {
t.Skip("doesn't really test anything, it just prints stuff...")
b := mustDecodeHex("0x02f8758401df5e7680832c8411832c8411830767f89452963ef50e27e06d72d59fcb4f3c2a687be3cfef880de0b6b3a764000080c080a094b11866f453ad85a980e0e8a2fc98cbaeb4409618c7734a7e12ae2f66fd405da042dbfb1b37af102023830ceeee0e703ffba0b8b3afeb8fe59f405eca9ed61072")
decoded, err := ParseEthTxArgs(b)
require.NoError(t, err)
orig, err := decoded.OriginalRlpMsg()
fmt.Println(hex.EncodeToString(orig))
// correct f4 addr: f410fkkld55ioe7qg24wvt7fu6pbknb56ht7pt4zamxa
sender, err := decoded.Sender()
require.NoError(t, err)
fmt.Println(decoded.Sender())
fmt.Printf("%+v\n", decoded)
addr, err := address.NewFromString("f410fkkld55ioe7qg24wvt7fu6pbknb56ht7pt4zamxa")
require.NoError(t, err)
require.Equal(t, sender, addr)
}

View File

@ -2,6 +2,7 @@ package stmgr
import (
"context"
"errors"
"fmt"
"reflect"
@ -27,6 +28,8 @@ import (
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
var ErrMetadataNotFound = errors.New("actor metadata not found")
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
act, err := sm.LoadActor(ctx, to, ts)
if err != nil {
@ -35,7 +38,7 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
m, found := sm.tsExec.NewActorRegistry().Methods[act.Code][method]
if !found {
return nil, fmt.Errorf("unknown method %d for actor %s", method, act.Code)
return nil, fmt.Errorf("unknown method %d for actor %s: %w", method, act.Code, ErrMetadataNotFound)
}
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
@ -44,7 +47,7 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
func GetParamType(ar *vm.ActorRegistry, actCode cid.Cid, method abi.MethodNum) (cbg.CBORUnmarshaler, error) {
m, found := ar.Methods[actCode][method]
if !found {
return nil, fmt.Errorf("unknown method %d for actor %s", method, actCode)
return nil, fmt.Errorf("unknown method %d for actor %s: %w", method, actCode, ErrMetadataNotFound)
}
return reflect.New(m.Params.Elem()).Interface().(cbg.CBORUnmarshaler), nil
}

View File

@ -2353,6 +2353,7 @@ Inputs:
Response:
```json
{
"hash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"parentHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"sha3Uncles": "0x0707070707070707070707070707070707070707070707070707070707070707",
"miner": "0x0707070707070707070707070707070707070707",
@ -2360,6 +2361,7 @@ Response:
"transactionsRoot": "0x0707070707070707070707070707070707070707070707070707070707070707",
"receiptsRoot": "0x0707070707070707070707070707070707070707070707070707070707070707",
"difficulty": "0x5",
"totalDifficulty": "0x5",
"number": "0x5",
"gasLimit": "0x5",
"gasUsed": "0x5",
@ -2394,6 +2396,7 @@ Inputs:
Response:
```json
{
"hash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"parentHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"sha3Uncles": "0x0707070707070707070707070707070707070707070707070707070707070707",
"miner": "0x0707070707070707070707070707070707070707",
@ -2401,6 +2404,7 @@ Response:
"transactionsRoot": "0x0707070707070707070707070707070707070707070707070707070707070707",
"receiptsRoot": "0x0707070707070707070707070707070707070707070707070707070707070707",
"difficulty": "0x5",
"totalDifficulty": "0x5",
"number": "0x5",
"gasLimit": "0x5",
"gasUsed": "0x5",
@ -2576,7 +2580,6 @@ Response:
"type": "0x5",
"input": "0x07",
"gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"v": "0x07",
@ -2613,7 +2616,6 @@ Response:
"type": "0x5",
"input": "0x07",
"gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"v": "0x07",
@ -2649,7 +2651,6 @@ Response:
"type": "0x5",
"input": "0x07",
"gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"v": "0x07",

View File

@ -0,0 +1 @@
608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061051c806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610193919061047e565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104b2565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b925082820261046081610337565b915082820484148315176104775761047661040d565b5b5092915050565b600061048982610337565b915061049483610337565b92508282039050818111156104ac576104ab61040d565b5b92915050565b60006104bd82610337565b91506104c883610337565b92508282019050808211156104e0576104df61040d565b5b9291505056fea26469706673582212205ede41ff9072784ccc19ac18de0781558d305a8139361fa85dc51a8614e47d8c64736f6c63430008110033

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.2;
contract SimpleCoin {
mapping(address => uint256) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor() {
balances[tx.origin] = 10000;
}
function sendCoin(address receiver, uint256 amount)
public
returns (bool sufficient)
{
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfer(msg.sender, receiver, amount);
return true;
}
function getBalanceInEth(address addr) public view returns (uint256) {
return getBalance(addr) * 2;
}
function getBalance(address addr) public view returns (uint256) {
return balances[addr];
}
}

171
itests/fevm_test.go Normal file
View File

@ -0,0 +1,171 @@
package itests
import (
"bytes"
"context"
"encoding/binary"
"encoding/hex"
"os"
"testing"
"time"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
builtintypes "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/itests/kit"
)
// TestFEVMBasic does a basic fevm contract installation and invocation
func TestFEVMBasic(t *testing.T) {
// TODO the contract installation and invocation can be lifted into utility methods
// He who writes the second test, shall do that.
kit.QuietMiningLogs()
blockTime := 100 * time.Millisecond
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// install contract
contractHex, err := os.ReadFile("contracts/SimpleCoin.bin")
require.NoError(t, err)
contract, err := hex.DecodeString(string(contractHex))
require.NoError(t, err)
fromAddr, err := client.WalletDefaultAddress(ctx)
require.NoError(t, err)
nonce, err := client.MpoolGetNonce(ctx, fromAddr)
if err != nil {
nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist).
}
var salt [32]byte
binary.BigEndian.PutUint64(salt[:], nonce)
method := builtintypes.MethodsEAM.Create2
params, err := actors.SerializeParams(&eam.Create2Params{
Initcode: contract,
Salt: salt,
})
require.NoError(t, err)
msg := &types.Message{
To: builtintypes.EthereumAddressManagerActorAddr,
From: fromAddr,
Value: big.Zero(),
Method: method,
Params: params,
}
t.Log("sending create message")
smsg, err := client.MpoolPushMessage(ctx, msg, nil)
require.NoError(t, err)
t.Log("waiting for message to execute")
wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
require.NoError(t, err)
require.True(t, wait.Receipt.ExitCode.IsSuccess(), "contract installation failed")
var result eam.CreateReturn
r := bytes.NewReader(wait.Receipt.Return)
err = result.UnmarshalCBOR(r)
require.NoError(t, err)
idAddr, err := address.NewIDAddress(result.ActorID)
require.NoError(t, err)
t.Logf("actor ID address is %s", idAddr)
// invoke the contract with owner
{
entryPoint, err := hex.DecodeString("f8b2cb4f")
require.NoError(t, err)
inputData, err := hex.DecodeString("000000000000000000000000ff00000000000000000000000000000000000064")
require.NoError(t, err)
params := append(entryPoint, inputData...)
var buffer bytes.Buffer
err = cbg.WriteByteArray(&buffer, params)
require.NoError(t, err)
params = buffer.Bytes()
msg := &types.Message{
To: idAddr,
From: fromAddr,
Value: big.Zero(),
Method: abi.MethodNum(2),
Params: params,
}
t.Log("sending invoke message")
smsg, err := client.MpoolPushMessage(ctx, msg, nil)
require.NoError(t, err)
t.Log("waiting for message to execute")
wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
require.NoError(t, err)
require.True(t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
require.NoError(t, err)
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000002710")
require.NoError(t, err)
require.Equal(t, result, expectedResult)
}
// invoke the contract with non owner
{
entryPoint, err := hex.DecodeString("f8b2cb4f")
require.NoError(t, err)
inputData, err := hex.DecodeString("000000000000000000000000ff00000000000000000000000000000000000065")
require.NoError(t, err)
params := append(entryPoint, inputData...)
var buffer bytes.Buffer
err = cbg.WriteByteArray(&buffer, params)
require.NoError(t, err)
params = buffer.Bytes()
msg := &types.Message{
To: idAddr,
From: fromAddr,
Value: big.Zero(),
Method: abi.MethodNum(2),
Params: params,
}
t.Log("sending invoke message")
smsg, err := client.MpoolPushMessage(ctx, msg, nil)
require.NoError(t, err)
t.Log("waiting for message to execute")
wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
require.NoError(t, err)
require.True(t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed")
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
require.NoError(t, err)
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
require.NoError(t, err)
require.Equal(t, result, expectedResult)
}
}

View File

@ -169,7 +169,7 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash,
if err != nil {
return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err)
}
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
return a.newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
}
func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) {
@ -183,7 +183,7 @@ func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, full
if err != nil {
return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err)
}
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
return a.newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
}
func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) {
@ -199,7 +199,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.Eth
return nil, nil
}
tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
tx, err := a.newEthTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil {
return nil, nil
}
@ -226,7 +226,7 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.Eth
return nil, nil
}
tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
tx, err := a.newEthTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil {
return nil, nil
}
@ -445,7 +445,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount api.EthUint64, n
for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) {
// Unfortunately we need to rebuild the full message view so we can
// totalize gas used in the tipset.
block, err := a.ethBlockFromFilecoinTipSet(ctx, ts, false)
block, err := a.newEthBlockFromFilecoinTipSet(ctx, ts, false)
if err != nil {
return api.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err)
}
@ -534,7 +534,7 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx api.EthByte
if err != nil {
return api.EmptyEthHash, err
}
return api.EthHashFromCid(cid)
return api.NewEthHashFromCid(cid)
}
func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx api.EthCall) (*types.Message, error) {
@ -666,7 +666,7 @@ func (a *EthModule) EthCall(ctx context.Context, tx api.EthCall, blkParam string
return api.EthBytes{}, nil
}
func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool) (api.EthBlock, error) {
func (a *EthModule) newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool) (api.EthBlock, error) {
parent, err := a.Chain.LoadTipSet(ctx, ts.Parents())
if err != nil {
return api.EthBlock{}, err
@ -675,7 +675,16 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
if err != nil {
return api.EthBlock{}, err
}
parentBlkHash, err := api.EthHashFromCid(parentKeyCid)
parentBlkHash, err := api.NewEthHashFromCid(parentKeyCid)
if err != nil {
return api.EthBlock{}, err
}
blkCid, err := ts.Key().Cid()
if err != nil {
return api.EthBlock{}, err
}
blkHash, err := api.NewEthHashFromCid(blkCid)
if err != nil {
return api.EthBlock{}, err
}
@ -698,13 +707,13 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
gasUsed += msgLookup.Receipt.GasUsed
if fullTxInfo {
tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
tx, err := a.newEthTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil {
return api.EthBlock{}, nil
}
block.Transactions = append(block.Transactions, tx)
} else {
hash, err := api.EthHashFromCid(msg.Cid())
hash, err := api.NewEthHashFromCid(msg.Cid())
if err != nil {
return api.EthBlock{}, err
}
@ -713,6 +722,7 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
}
}
block.Hash = blkHash
block.Number = api.EthUint64(ts.Height())
block.ParentHash = parentBlkHash
block.Timestamp = api.EthUint64(ts.Blocks()[0].Timestamp)
@ -765,12 +775,12 @@ func (a *EthModule) lookupEthAddress(ctx context.Context, addr address.Address)
return api.EthAddressFromFilecoinAddress(idAddr)
}
func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) {
func (a *EthModule) newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) {
if msgLookup == nil {
return api.EthTx{}, fmt.Errorf("msg does not exist")
}
cid := msgLookup.Message
txHash, err := api.EthHashFromCid(cid)
txHash, err := api.NewEthHashFromCid(cid)
if err != nil {
return api.EthTx{}, err
}
@ -791,7 +801,7 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
return api.EthTx{}, err
}
blkHash, err := api.EthHashFromCid(parentTsCid)
blkHash, err := api.NewEthHashFromCid(parentTsCid)
if err != nil {
return api.EthTx{}, err
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"strconv"
@ -617,14 +618,22 @@ func (m *StateModule) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence
t, err := stmgr.GetReturnType(ctx, m.StateManager, vmsg.To, vmsg.Method, ts)
if err != nil {
return nil, xerrors.Errorf("failed to get return type: %w", err)
if errors.Is(err, stmgr.ErrMetadataNotFound) {
// This is not nececessary an error -- EVM methods (and in the future native actors) may
// return just bytes, and in the not so distant future we'll have native wasm actors
// that are by definition not in the registry.
// So in this case, log a debug message and retun the raw bytes.
log.Debugf("failed to get return type: %s", err)
returndec = recpt.Return
} else {
return nil, xerrors.Errorf("failed to get return type: %w", err)
}
} else {
if err := t.UnmarshalCBOR(bytes.NewReader(recpt.Return)); err != nil {
return nil, err
}
returndec = t
}
if err := t.UnmarshalCBOR(bytes.NewReader(recpt.Return)); err != nil {
return nil, err
}
returndec = t
}
return &api.MsgLookup{