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: ethrpc: implement eth_sendRawTransaction #5571

Merged
merged 2 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ import (
"github.com/filecoin-project/venus/pkg/chain"
"github.com/filecoin-project/venus/pkg/clock"
"github.com/filecoin-project/venus/pkg/config"
_ "github.com/filecoin-project/venus/pkg/crypto/bls" // enable bls signatures
_ "github.com/filecoin-project/venus/pkg/crypto/secp" // enable secp signatures
_ "github.com/filecoin-project/venus/pkg/crypto/bls" // enable bls signatures
_ "github.com/filecoin-project/venus/pkg/crypto/delegated" // enable delegated signatures
_ "github.com/filecoin-project/venus/pkg/crypto/secp" // enable secp signatures
"github.com/filecoin-project/venus/pkg/metrics"
"github.com/filecoin-project/venus/pkg/repo"
cmds "github.com/ipfs/go-ipfs-cmds"
Expand Down
132 changes: 112 additions & 20 deletions app/submodule/eth/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import (
"fmt"
"strconv"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
actorstypes "github.com/filecoin-project/go-state-types/actors"
"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/evm"
init10 "github.com/filecoin-project/go-state-types/builtin/v10/init"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/venus/pkg/constants"
"github.com/filecoin-project/venus/pkg/fork"
"github.com/filecoin-project/venus/pkg/vm/vmcontext"
"github.com/filecoin-project/venus/venus-shared/actors"
builtinactors "github.com/filecoin-project/venus/venus-shared/actors/builtin"
v1 "github.com/filecoin-project/venus/venus-shared/api/chain/v1"
"github.com/filecoin-project/venus/venus-shared/types"
)
Expand Down Expand Up @@ -71,27 +78,41 @@ func (a *ethAPI) EthGetBlockByHash(ctx context.Context, blkHash types.EthHash, f
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
}

func (a *ethAPI) EthGetBlockByNumber(ctx context.Context, blkNum types.EthInt, fullTxInfo bool) (types.EthBlock, error) {
ts, err := a.em.chainModule.ChainReader.GetTipSetByHeight(ctx, nil, abi.ChainEpoch(blkNum), false)
func (a *ethAPI) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (types.EthBlock, error) {
var num types.EthInt
err := num.UnmarshalJSON([]byte(`"` + blkNum + `"`))
if err != nil {
head, err := a.chain.ChainHead(ctx)
if err != nil {
return types.EthBlock{}, fmt.Errorf("failed to got head %v", err)
}
num = types.EthInt(head.Height())
}
ts, err := a.em.chainModule.ChainReader.GetTipSetByHeight(ctx, nil, abi.ChainEpoch(num), false)
if err != nil {
return types.EthBlock{}, fmt.Errorf("error loading tipset %s: %w", ts, err)
}
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
}

func (a *ethAPI) EthGetTransactionByHash(ctx context.Context, txHash types.EthHash) (types.EthTx, error) {
func (a *ethAPI) EthGetTransactionByHash(ctx context.Context, txHash *types.EthHash) (*types.EthTx, error) {
// Ethereum's behavior is to return null when the txHash is invalid, so we use nil to check if txHash is valid
if txHash == nil {
return nil, nil
}

cid := txHash.ToCid()

msgLookup, err := a.chain.StateSearchMsg(ctx, types.EmptyTSK, cid, constants.LookbackNoLimit, true)
if err != nil {
return types.EthTx{}, nil
return nil, nil
}

tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil {
return types.EthTx{}, err
return nil, err
}
return tx, nil
return &tx, nil
}

func (a *ethAPI) EthGetTransactionCount(ctx context.Context, sender types.EthAddress, blkParam string) (types.EthInt, error) {
Expand All @@ -107,7 +128,7 @@ func (a *ethAPI) EthGetTransactionCount(ctx context.Context, sender types.EthAdd
}

// todo: 实现 StateReplay 接口
func (a *ethAPI) EthGetTransactionReceipt(ctx context.Context, txHash types.EthHash) (types.EthTxReceipt, error) {
func (a *ethAPI) EthGetTransactionReceipt(ctx context.Context, txHash types.EthHash) (*types.EthTxReceipt, error) {
// cid := txHash.ToCid()

// msgLookup, err := a.chain.StateSearchMsg(ctx, types.EmptyTSK, cid, constants.LookbackNoLimit, true)
Expand All @@ -130,7 +151,7 @@ func (a *ethAPI) EthGetTransactionReceipt(ctx context.Context, txHash types.EthH
// return types.EthTxReceipt{}, err
// }
// return receipt, nil
return types.EthTxReceipt{}, nil
return &types.EthTxReceipt{}, nil
}

func (a *ethAPI) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash types.EthHash, txIndex types.EthInt) (types.EthTx, error) {
Expand Down Expand Up @@ -218,24 +239,92 @@ func (a *ethAPI) EthGasPrice(ctx context.Context) (types.EthBigInt, error) {
}

func (a *ethAPI) EthSendRawTransaction(ctx context.Context, rawTx types.EthBytes) (types.EthHash, error) {
return types.EthHash{}, nil
}
txArgs, err := types.ParseEthTxArgs(rawTx)
if err != nil {
return types.EmptyEthHash, err
}

func (a *ethAPI) applyEvmMsg(ctx context.Context, tx types.EthCall) (*types.InvocResult, error) {
from, err := tx.From.ToFilecoinAddress()
smsg, err := txArgs.ToSignedMessage()
if err != nil {
return nil, err
return types.EmptyEthHash, err
}
to, err := tx.To.ToFilecoinAddress()
cid, err := a.mpool.MpoolPush(ctx, smsg)
if err != nil {
return nil, fmt.Errorf("cannot get Filecoin address: %w", err)
return types.EmptyEthHash, err
}
return types.EthHashFromCid(cid)
}

func (a *ethAPI) applyEvmMsg(ctx context.Context, tx types.EthCall) (*types.InvocResult, error) {
// FIXME: this is a workaround, remove this when f4 address is ready
var from address.Address
var err error
if tx.From[0] == 0xff && tx.From[1] == 0 && tx.From[2] == 0 {
addr, err := tx.From.ToFilecoinAddress()
if err != nil {
return nil, err
}
from = addr
} else {
id := uint64(100)
for ; id < 300; id++ {
idAddr, err := address.NewIDAddress(id)
if err != nil {
return nil, err
}
from = idAddr
act, err := a.chain.StateGetActor(ctx, idAddr, types.EmptyTSK)
if err != nil {
return nil, err
}
if builtinactors.IsAccountActor(act.Code) {
break
}
}
if id == 300 {
return nil, fmt.Errorf("cannot find a dummy account")
}
}

var params []byte
var to address.Address
if tx.To == nil {
to = builtintypes.InitActorAddr
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
Creator: tx.Data,
Initcode: []byte{},
})
if err != nil {
return nil, fmt.Errorf("failed to serialize constructor params: %w", err)
}

evmActorCid, ok := actors.GetActorCodeID(actorstypes.Version8, "evm")
if !ok {
return nil, fmt.Errorf("failed to lookup evm actor code CID")
}

params, err = actors.SerializeParams(&init10.ExecParams{
CodeCID: evmActorCid,
ConstructorParams: constructorParams,
})
if err != nil {
return nil, fmt.Errorf("failed to serialize init actor exec params: %w", err)
}
} else {
addr, err := tx.To.ToFilecoinAddress()
if err != nil {
return nil, fmt.Errorf("cannot get Filecoin address: %w", err)
}
to = addr
params = tx.Data
}

msg := &types.Message{
From: from,
To: to,
Value: big.Int(tx.Value),
Method: abi.MethodNum(2),
Params: tx.Data,
Params: params,
GasLimit: constants.BlockGasLimit,
GasFeeCap: big.Zero(),
GasPremium: big.Zero(),
Expand Down Expand Up @@ -277,7 +366,7 @@ func (a *ethAPI) applyEvmMsg(ctx context.Context, tx types.EthCall) (*types.Invo
}, nil
}

func (a *ethAPI) EthEstimateGas(ctx context.Context, tx types.EthCall, blkParam string) (types.EthInt, error) {
func (a *ethAPI) EthEstimateGas(ctx context.Context, tx types.EthCall) (types.EthInt, error) {
invokeResult, err := a.applyEvmMsg(ctx, tx)
if err != nil {
return types.EthInt(0), err
Expand Down Expand Up @@ -355,6 +444,9 @@ func (a *ethAPI) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSe
}

func (a *ethAPI) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *types.MsgLookup) (types.EthTx, error) {
if msgLookup == nil {
return types.EthTx{}, fmt.Errorf("msg does not exist")
}
cid := msgLookup.Message
txHash, err := types.EthHashFromCid(cid)
if err != nil {
Expand Down Expand Up @@ -414,9 +506,9 @@ func (a *ethAPI) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *
Gas: types.EthInt(msg.GasLimit),
MaxFeePerGas: types.EthBigInt(msg.GasFeeCap),
MaxPriorityFeePerGas: types.EthBigInt(msg.GasPremium),
V: types.EthBigIntZero,
R: types.EthBigIntZero,
S: types.EthBigIntZero,
V: types.EthBytes{},
R: types.EthBytes{},
S: types.EthBytes{},
Input: msg.Params,
}
return tx, nil
Expand Down
4 changes: 3 additions & 1 deletion app/submodule/mining/mining_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (miningAPI *MiningAPI) minerCreateBlock(ctx context.Context, bt *types.Bloc
}

blsMsgCids = append(blsMsgCids, c)
} else {
} else if msg.Signature.Type == crypto.SigTypeSecp256k1 || msg.Signature.Type == crypto.SigTypeDelegated {
c, err := messageStore.StoreMessage(msg)
if err != nil {
return nil, err
Expand All @@ -229,6 +229,8 @@ func (miningAPI *MiningAPI) minerCreateBlock(ctx context.Context, bt *types.Bloc
secpkMsgCids = append(secpkMsgCids, c)
secpkMessages = append(secpkMessages, msg)

} else {
return nil, fmt.Errorf("unknown sig type: %d", msg.Signature.Type)
}
}
store := miningAPI.Ming.BlockStore.Blockstore
Expand Down
1 change: 1 addition & 0 deletions app/submodule/wallet/remotewallet/keymap.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
var keyMapper = map[address.Protocol]types.KeyType{
address.SECP256K1: types.KTSecp256k1,
address.BLS: types.KTBLS,
address.Delegated: types.KTDelegated,
}

func GetKeyType(p address.Protocol) types.KeyType {
Expand Down
3 changes: 3 additions & 0 deletions cmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/filecoin-project/venus/fixtures/assets"
"github.com/filecoin-project/venus/fixtures/networks"
"github.com/filecoin-project/venus/venus-shared/actors"
"github.com/filecoin-project/venus/venus-shared/types"
"github.com/filecoin-project/venus/venus-shared/utils"

"github.com/filecoin-project/venus/pkg/util/ulimit"
Expand Down Expand Up @@ -179,6 +180,8 @@ func daemonRun(req *cmds.Request, re cmds.ResponseEmitter) error {
return err
}
utils.ReloadMethodsMap()
types.SetEip155ChainId(config.NetworkParams.Eip155ChainID)
log.Infof("Eip155ChainId %v", types.Eip155ChainID)

// second highest precedence is env vars.
if envAPI := os.Getenv("VENUS_API"); envAPI != "" {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ require (
github.com/raulk/clock v1.1.0
github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e
github.com/stretchr/testify v1.8.0
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722
github.com/whyrusleeping/go-logging v0.0.1
github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1
go.opencensus.io v0.23.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1706,8 +1706,8 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f
github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c h1:6VPKXBDRt7mDUyiHx9X8ROnPYFDf3L7OfEuKCI5dZDI=
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722 h1:0HEhvpGQJ2Gd0ngPW83aduQQuF/V9v13+3zpSrR3lrA=
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
Expand Down
4 changes: 4 additions & 0 deletions pkg/chainsync/syncer/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/filecoin-project/venus/pkg/consensus"
"github.com/filecoin-project/venus/pkg/crypto"
"github.com/filecoin-project/venus/pkg/statemanger"
"github.com/hashicorp/go-multierror"

Expand Down Expand Up @@ -553,6 +554,9 @@ func (syncer *Syncer) fetchSegMessage(ctx context.Context, segTipset []*types.Ti
}

for _, m := range messages[index].Secpk {
if m.Signature.Type != crypto.SigTypeSecp256k1 && m.Signature.Type != crypto.SigTypeDelegated {
return nil, fmt.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
}
if _, err := cborStore.Put(ctx, m); err != nil {
return nil, fmt.Errorf("SECP message processing failed: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ type NetworkParamsConfig struct {
PropagationDelaySecs uint64 `json:"-"`
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
// As per https://github.com/ethereum-lists/chains
Eip155ChainID uint64 `json:"-"`
Eip155ChainID int `json:"-"`
}

// ForkUpgradeConfig record upgrade parameters
Expand Down
2 changes: 1 addition & 1 deletion pkg/consensus/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ func (bv *BlockValidator) checkBlockMessages(ctx context.Context, sigValidator *
secpMsgs := make([]types.ChainMsg, len(blksecpMsgs))
for i, m := range blksecpMsgs {
if bv.fork.GetNetworkVersion(ctx, blk.Height) >= network.Version14 {
if m.Signature.Type != crypto.SigTypeSecp256k1 {
if m.Signature.Type != crypto.SigTypeSecp256k1 && m.Signature.Type != crypto.SigTypeDelegated {
return fmt.Errorf("block had invalid secpk message at index %d: %w", i, err)
}
}
Expand Down
65 changes: 65 additions & 0 deletions pkg/crypto/delegated/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package delegated

import (
"fmt"
"io"

"golang.org/x/crypto/sha3"

"github.com/filecoin-project/go-address"
gocrypto "github.com/filecoin-project/go-crypto"
crypto1 "github.com/filecoin-project/go-state-types/crypto"
crypto2 "github.com/filecoin-project/venus/pkg/crypto"
)

type delegatedSigner struct{}

func (delegatedSigner) GenPrivate() ([]byte, error) {
priv, err := gocrypto.GenerateKey()
if err != nil {
return nil, err
}
return priv, nil
}

func (delegatedSigner) GenPrivateFromSeed(seed io.Reader) ([]byte, error) {
return gocrypto.GenerateKeyFromSeed(seed)
}

func (delegatedSigner) ToPublic(pk []byte) ([]byte, error) {
return gocrypto.PublicKey(pk), nil
}

func (delegatedSigner) Sign(pk []byte, msg []byte) ([]byte, error) {
return nil, fmt.Errorf("not implemented")
}

func (delegatedSigner) Verify(sig []byte, a address.Address, msg []byte) error {
hasher := sha3.NewLegacyKeccak256()
hasher.Write(msg)
hash := hasher.Sum(nil)

pubk, err := gocrypto.EcRecover(hash, sig)
if err != nil {
return err
}

maybeaddr, err := address.NewSecp256k1Address(pubk)
if err != nil {
return err
}

if maybeaddr != a {
return fmt.Errorf("signature did not match")
}

return nil
}

func (delegatedSigner) VerifyAggregate(pubKeys, msgs [][]byte, signature []byte) bool {
panic("not support")
}

func init() {
crypto2.RegisterSignature(crypto1.SigTypeDelegated, delegatedSigner{})
}
Loading