Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/transport nv18 rc2 #5738

Merged
merged 11 commits into from
Feb 20, 2023
2 changes: 1 addition & 1 deletion app/submodule/blockstore/blockstore_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (

"github.com/filecoin-project/venus/venus-shared/types"

blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid"
offline "github.com/ipfs/go-ipfs-exchange-offline"
ipld "github.com/ipfs/go-ipld-format"
blocks "github.com/ipfs/go-libipfs/blocks"
"github.com/ipfs/go-merkledag"

v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
Expand Down
5 changes: 5 additions & 0 deletions app/submodule/eth/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/ipfs/go-cid"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-jsonrpc"
v1 "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
Expand All @@ -31,6 +32,10 @@ func (e *ethAPIDummy) EthAccounts(ctx context.Context) ([]types.EthAddress, erro
return nil, ErrModuleDisabled
}

func (e *ethAPIDummy) EthAddressToFilecoinAddress(ctx context.Context, ethAddress types.EthAddress) (address.Address, error) {
return address.Undef, ErrModuleDisabled
}

func (e *ethAPIDummy) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum types.EthUint64) (types.EthUint64, error) {
return 0, ErrModuleDisabled
}
Expand Down
169 changes: 157 additions & 12 deletions app/submodule/eth/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/filecoin-project/venus/pkg/statemanger"
"github.com/filecoin-project/venus/venus-shared/actors"
builtinactors "github.com/filecoin-project/venus/venus-shared/actors/builtin"
builtinevm "github.com/filecoin-project/venus/venus-shared/actors/builtin/evm"
types2 "github.com/filecoin-project/venus/venus-shared/actors/types"
v1 "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
Expand Down Expand Up @@ -139,6 +140,10 @@ func (a *ethAPI) EthAccounts(context.Context) ([]types.EthAddress, error) {
return []types.EthAddress{}, nil
}

func (a *ethAPI) EthAddressToFilecoinAddress(ctx context.Context, ethAddress types.EthAddress) (address.Address, error) {
return ethAddress.ToFilecoinAddress()
}

func (a *ethAPI) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, error) {
msgs, err := a.em.chainModule.MessageStore.MessagesForTipset(ts)
if err != nil {
Expand Down Expand Up @@ -317,6 +322,27 @@ func (a *ethAPI) EthGetTransactionCount(ctx context.Context, sender types.EthAdd
if err != nil {
return types.EthUint64(0), fmt.Errorf("cannot parse block param: %s", blkParam)
}

// First, handle the case where the "sender" is an EVM actor.
if actor, err := a.em.chainModule.Stmgr.GetActorAt(ctx, addr, ts); err != nil {
if errors.Is(err, types.ErrActorNotFound) {
return 0, nil
}
return 0, fmt.Errorf("failed to lookup contract %s: %w", sender, err)
} else if builtinactors.IsEvmActor(actor.Code) {
evmState, err := builtinevm.Load(a.em.chainModule.ChainReader.Store(ctx), actor)
if err != nil {
return 0, fmt.Errorf("failed to load evm state: %w", err)
}
if alive, err := evmState.IsAlive(); err != nil {
return 0, err
} else if !alive {
return 0, nil
}
nonce, err := evmState.Nonce()
return types.EthUint64(nonce), err
}

nonce, err := a.em.mpoolModule.MPool.GetNonce(ctx, addr, ts.Key())
if err != nil {
return types.EthUint64(0), err
Expand Down Expand Up @@ -460,13 +486,18 @@ func (a *ethAPI) EthGetCode(ctx context.Context, ethAddr types.EthAddress, blkPa
}

func (a *ethAPI) EthGetStorageAt(ctx context.Context, ethAddr types.EthAddress, position types.EthBytes, blkParam string) (types.EthBytes, error) {
ts, err := a.parseBlkParam(ctx, blkParam)
if err != nil {
return nil, fmt.Errorf("cannot parse block param: %s", blkParam)
}

l := len(position)
if l > 32 {
return nil, fmt.Errorf("supplied storage key is too long")
}

// pad with zero bytes if smaller than 32 bytes
position = append(make([]byte, 32-l), position...)
position = append(make([]byte, 32-l, 32), position...)

to, err := ethAddr.ToFilecoinAddress()
if err != nil {
Expand All @@ -479,6 +510,18 @@ func (a *ethAPI) EthGetStorageAt(ctx context.Context, ethAddr types.EthAddress,
return nil, fmt.Errorf("failed to construct system sender address: %w", err)
}

actor, err := a.em.chainModule.Stmgr.GetActorAt(ctx, to, ts)
if err != nil {
if errors.Is(err, types.ErrActorNotFound) {
return types.EthBytes(make([]byte, 32)), nil
}
return nil, fmt.Errorf("failed to lookup contract %s: %w", ethAddr, err)
}

if !builtinactors.IsEvmActor(actor.Code) {
return types.EthBytes(make([]byte, 32)), nil
}

params, err := actors.SerializeParams(&evm.GetStorageAtParams{
StorageKey: *(*[32]byte)(position),
})
Expand All @@ -497,11 +540,6 @@ func (a *ethAPI) EthGetStorageAt(ctx context.Context, ethAddr types.EthAddress,
GasPremium: big.Zero(),
}

ts, err := a.chain.ChainHead(ctx)
if err != nil {
return nil, fmt.Errorf("failed to got head %v", err)
}

// Try calling until we find a height with no migration.
var res *types.InvocResult
for {
Expand All @@ -523,7 +561,19 @@ func (a *ethAPI) EthGetStorageAt(ctx context.Context, ethAddr types.EthAddress,
return nil, fmt.Errorf("no message receipt")
}

return res.MsgRct.Return, nil
if res.MsgRct.ExitCode.IsError() {
return nil, fmt.Errorf("failed to lookup storage slot: %s", res.Error)
}

var ret abi.CborBytes
if err := ret.UnmarshalCBOR(bytes.NewReader(res.MsgRct.Return)); err != nil {
return nil, fmt.Errorf("failed to unmarshal storage slot: %w", err)
}

// pad with zero bytes if smaller than 32 bytes
ret = append(make([]byte, 32-len(ret), 32), ret...)

return types.EthBytes(ret), nil
}

func (a *ethAPI) EthGetBalance(ctx context.Context, address types.EthAddress, blkParam string) (types.EthBigInt, error) {
Expand Down Expand Up @@ -806,7 +856,8 @@ func (a *ethAPI) applyMessage(ctx context.Context, msg *types.Message, tsk types
return nil, fmt.Errorf("no message receipt")
}
if res.MsgRct.ExitCode.IsError() {
return nil, fmt.Errorf("message execution failed: exit %s, msg receipt return: %s, reason: %v", res.MsgRct.ExitCode, res.MsgRct.Return, res.Error)
reason := parseEthRevert(res.MsgRct.Return)
return nil, fmt.Errorf("message execution failed: exit %s, revert reason: %s, vm error: %s", res.MsgRct.ExitCode, reason, res.Error)
}

return res, nil
Expand All @@ -825,14 +876,27 @@ func (a *ethAPI) EthEstimateGas(ctx context.Context, tx types.EthCall) (types.Et
if err != nil {
return types.EthUint64(0), err
}
msg, err = a.mpool.GasEstimateMessageGas(ctx, msg, nil, ts.Key())
gassedMsg, err := a.mpool.GasEstimateMessageGas(ctx, msg, nil, ts.Key())
if err != nil {
return types.EthUint64(0), fmt.Errorf("failed to estimate gas: %w", err)
}
if err != nil {
// On failure, GasEstimateMessageGas doesn't actually return the invocation result,
// it just returns an error. That means we can't get the revert reason.
//
// So we re-execute the message with EthCall (well, applyMessage which contains the
// guts of EthCall). This will give us an ethereum specific error with revert
// information.
msg.GasLimit = constants.BlockGasLimit
if _, err2 := a.applyMessage(ctx, msg, ts.Key()); err2 != nil {
err = err2
}
return types.EthUint64(0), fmt.Errorf("failed to estimate gas: %w", err)
}

expectedGas, err := ethGasSearch(ctx, a.em.chainModule.Stmgr, a.em.mpoolModule.MPool, msg, ts)
expectedGas, err := ethGasSearch(ctx, a.em.chainModule.Stmgr, a.em.mpoolModule.MPool, gassedMsg, ts)
if err != nil {
log.Errorw("expected gas", "err", err)
return 0, fmt.Errorf("gas search failed: %w", err)
}

return types.EthUint64(expectedGas), nil
Expand Down Expand Up @@ -967,7 +1031,7 @@ func (a *ethAPI) EthCall(ctx context.Context, tx types.EthCall, blkParam string)

invokeResult, err := a.applyMessage(ctx, msg, ts.Key())
if err != nil {
return nil, fmt.Errorf("failed to apply message: %w", err)
return nil, err
}

if msg.To == builtintypes.EthereumAddressManagerActorAddr {
Expand Down Expand Up @@ -1424,11 +1488,13 @@ func (m *ethTxHashManager) ProcessSignedMessage(ctx context.Context, msg *types.
ethTx, err := newEthTxFromSignedMessage(ctx, msg, m.chainAPI)
if err != nil {
log.Errorf("error converting filecoin message to eth tx: %s", err)
return
}

err = m.TransactionHashLookup.UpsertHash(ethTx.Hash, msg.Cid())
if err != nil {
log.Errorf("error inserting tx mapping to db: %s", err)
return
}
}

Expand Down Expand Up @@ -1479,6 +1545,85 @@ func parseEthTopics(topics types.EthTopicSpec) (map[string][][]byte, error) {
return keys, nil
}

const errorFunctionSelector = "\x08\xc3\x79\xa0" // Error(string)
const panicFunctionSelector = "\x4e\x48\x7b\x71" // Panic(uint256)
// Eth ABI (solidity) panic codes.
var panicErrorCodes = map[uint64]string{
0x00: "Panic()",
0x01: "Assert()",
0x11: "ArithmeticOverflow()",
0x12: "DivideByZero()",
0x21: "InvalidEnumVariant()",
0x22: "InvalidStorageArray()",
0x31: "PopEmptyArray()",
0x32: "ArrayIndexOutOfBounds()",
0x41: "OutOfMemory()",
0x51: "CalledUninitializedFunction()",
}

// Parse an ABI encoded revert reason. This reason should be encoded as if it were the parameters to
// an `Error(string)` function call.
//
// See https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require
func parseEthRevert(ret []byte) string {
if len(ret) == 0 {
return "none"
}
var cbytes abi.CborBytes
if err := cbytes.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return "ERROR: revert reason is not cbor encoded bytes"
}
if len(cbytes) == 0 {
return "none"
}
// If it's not long enough to contain an ABI encoded response, return immediately.
if len(cbytes) < 4+32 {
return types.EthBytes(cbytes).String()
}
switch string(cbytes[:4]) {
case panicFunctionSelector:
cbytes := cbytes[4 : 4+32]
// Read the and check the code.
code, err := types.EthUint64FromBytes(cbytes)
if err != nil {
// If it's too big, just return the raw value.
codeInt := big.PositiveFromUnsignedBytes(cbytes)
return fmt.Sprintf("Panic(%s)", types.EthBigInt(codeInt).String())
}
if s, ok := panicErrorCodes[uint64(code)]; ok {
return s
}
return fmt.Sprintf("Panic(0x%x)", code)
case errorFunctionSelector:
cbytes := cbytes[4:]
cbytesLen := types.EthUint64(len(cbytes))
// Read the and check the offset.
offset, err := types.EthUint64FromBytes(cbytes[:32])
if err != nil {
break
}
if cbytesLen < offset {
break
}

// Read and check the length.
if cbytesLen-offset < 32 {
break
}
start := offset + 32
length, err := types.EthUint64FromBytes(cbytes[offset : offset+32])
if err != nil {
break
}
if cbytesLen-start < length {
break
}
// Slice the error message.
return fmt.Sprintf("Error(%s)", cbytes[start:start+length])
}
return types.EthBytes(cbytes).String()
}

func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]types.EthBigInt, uint64) {
var totalGasUsed uint64
for _, tx := range txGasRewards {
Expand Down
2 changes: 1 addition & 1 deletion app/submodule/network/network_submodule.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/dchest/blake2b"
"github.com/ipfs/go-bitswap"
bsnet "github.com/ipfs/go-bitswap/network"
blocks "github.com/ipfs/go-block-format"
bserv "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
Expand All @@ -23,6 +22,7 @@ import (
"github.com/ipfs/go-graphsync/storeutil"
exchange "github.com/ipfs/go-ipfs-exchange-interface"
cbor "github.com/ipfs/go-ipld-cbor"
blocks "github.com/ipfs/go-libipfs/blocks"
logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p"
dht "github.com/libp2p/go-libp2p-kad-dht"
Expand Down
15 changes: 11 additions & 4 deletions cmd/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/filecoin-project/venus/app/node"
"github.com/filecoin-project/venus/pkg/constants"
"github.com/filecoin-project/venus/venus-shared/actors"
"github.com/filecoin-project/venus/venus-shared/actors/builtin"
v1api "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
)
Expand Down Expand Up @@ -76,16 +77,22 @@ var evmGetInfoCmd = &cmds.Command{
}

actor, err := chainAPI.StateGetActor(ctx, faddr, types.EmptyTSK)
if err != nil {
return err
}

buf := new(bytes.Buffer)
writer := NewSilentWriter(buf)

writer.Println("Filecoin address: ", faddr)
writer.Println("Eth address: ", eaddr)
writer.Println("Code cid: ", actor.Code.String())
if err != nil {
writer.Printf("Actor lookup failed for faddr %s with error: %s\n", faddr, err)
} else {
idAddr, err := chainAPI.StateLookupID(ctx, faddr, types.EmptyTSK)
if err == nil {
writer.Println("ID address: ", idAddr)
writer.Println("Code cid: ", actor.Code.String())
writer.Println("Actor Type: ", builtin.ActorNameByCode(actor.Code))
}
}

return re.Emit(buf)
},
Expand Down
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ require (
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
github.com/ipfs-force-community/metrics v1.0.1-0.20211022060227-11142a08b729
github.com/ipfs/go-bitswap v0.10.2
github.com/ipfs/go-block-format v0.0.3
github.com/ipfs/go-blockservice v0.4.0
github.com/ipfs/go-cid v0.3.2
github.com/ipfs/go-datastore v0.6.0
Expand All @@ -75,6 +74,7 @@ require (
github.com/ipfs/go-ipfs-files v0.1.1
github.com/ipfs/go-ipld-cbor v0.0.6
github.com/ipfs/go-ipld-format v0.4.0
github.com/ipfs/go-libipfs v0.4.1
github.com/ipfs/go-log v1.0.5
github.com/ipfs/go-log/v2 v2.5.1
github.com/ipfs/go-merkledag v0.8.1
Expand Down Expand Up @@ -116,6 +116,8 @@ require (
gotest.tools v2.2.0+incompatible
)

require github.com/ipfs/go-block-format v0.1.1 // indirect

require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/Kubuxu/go-os-helper v0.0.1 // indirect
Expand Down Expand Up @@ -189,13 +191,12 @@ require (
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect
github.com/ipfs/go-ipfs-pq v0.0.2 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
github.com/ipfs/go-ipns v0.3.0 // indirect
github.com/ipfs/go-libipfs v0.1.0 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
github.com/ipfs/go-peertaskqueue v0.8.0 // indirect
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
github.com/ipfs/go-unixfsnode v1.4.0 // indirect
github.com/ipfs/go-verifcid v0.0.2 // indirect
github.com/ipld/go-codec-dagpb v1.5.0 // indirect
Expand Down
Loading