Skip to content

Commit

Permalink
Merge pull request #5571 from filecoin-project/feat/eth-signature
Browse files Browse the repository at this point in the history
feat: ethrpc: implement eth_sendRawTransaction
  • Loading branch information
diwufeiwen authored Dec 15, 2022
2 parents 37a8393 + fdadbd4 commit 706224d
Show file tree
Hide file tree
Showing 37 changed files with 1,433 additions and 116 deletions.
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

0 comments on commit 706224d

Please sign in to comment.