api: ethrpc: implement eth_sendRawTransaction (#9334)

Co-authored-by: Raúl Kripalani <raul@protocol.ai>
This commit is contained in:
Kevin Li 2022-09-29 16:46:59 -04:00 committed by vyzo
parent b53d5924a1
commit 6c7fd94aa7
32 changed files with 1364 additions and 127 deletions

View File

@ -771,10 +771,10 @@ type FullNode interface {
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash EthHash) (EthInt, error) //perm:read EthGetBlockTransactionCountByHash(ctx context.Context, blkHash EthHash) (EthInt, error) //perm:read
EthGetBlockByHash(ctx context.Context, blkHash EthHash, fullTxInfo bool) (EthBlock, error) //perm:read EthGetBlockByHash(ctx context.Context, blkHash EthHash, fullTxInfo bool) (EthBlock, error) //perm:read
EthGetBlockByNumber(ctx context.Context, blkNum EthInt, fullTxInfo bool) (EthBlock, error) //perm:read EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (EthBlock, error) //perm:read
EthGetTransactionByHash(ctx context.Context, txHash EthHash) (EthTx, error) //perm:read EthGetTransactionByHash(ctx context.Context, txHash *EthHash) (*EthTx, error) //perm:read
EthGetTransactionCount(ctx context.Context, sender EthAddress, blkOpt string) (EthInt, error) //perm:read EthGetTransactionCount(ctx context.Context, sender EthAddress, blkOpt string) (EthInt, error) //perm:read
EthGetTransactionReceipt(ctx context.Context, txHash EthHash) (EthTxReceipt, error) //perm:read EthGetTransactionReceipt(ctx context.Context, txHash EthHash) (*EthTxReceipt, error) //perm:read
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash EthHash, txIndex EthInt) (EthTx, error) //perm:read EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash EthHash, txIndex EthInt) (EthTx, error) //perm:read
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum EthInt, txIndex EthInt) (EthTx, error) //perm:read EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum EthInt, txIndex EthInt) (EthTx, error) //perm:read
@ -787,9 +787,9 @@ type FullNode interface {
EthProtocolVersion(ctx context.Context) (EthInt, error) //perm:read EthProtocolVersion(ctx context.Context) (EthInt, error) //perm:read
EthGasPrice(ctx context.Context) (EthBigInt, error) //perm:read EthGasPrice(ctx context.Context) (EthBigInt, error) //perm:read
EthMaxPriorityFeePerGas(ctx context.Context) (EthBigInt, error) //perm:read EthMaxPriorityFeePerGas(ctx context.Context) (EthBigInt, error) //perm:read
EthEstimateGas(ctx context.Context, tx EthCall, blkParam string) (EthInt, error) //perm:read EthEstimateGas(ctx context.Context, tx EthCall) (EthInt, error) //perm:read
EthCall(ctx context.Context, tx EthCall, blkParam string) (EthBytes, error) //perm:read EthCall(ctx context.Context, tx EthCall, blkParam string) (EthBytes, error) //perm:read
EthSendRawTransaction(ctx context.Context, rawTx EthBytes) (EthHash, error) //perm:read EthSendRawTransaction(ctx context.Context, rawTx EthBytes) (EthHash, error) //perm:read

View File

@ -346,6 +346,7 @@ func init() {
Conns: 4, Conns: 4,
FD: 5, FD: 5,
}) })
addExample(map[string]bitfield.BitField{ addExample(map[string]bitfield.BitField{
"": bitfield.NewFromSet([]uint64{5, 6, 7, 10}), "": bitfield.NewFromSet([]uint64{5, 6, 7, 10}),
}) })
@ -361,6 +362,15 @@ func init() {
Headers: nil, Headers: nil,
}, },
}) })
ethint := api.EthInt(5)
addExample(ethint)
addExample(&ethint)
ethaddr, _ := api.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031")
addExample(&ethaddr)
ethhash, _ := api.EthHashFromCid(c)
addExample(&ethhash)
} }
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {

478
api/eth_transactions.go Normal file
View File

@ -0,0 +1,478 @@
package api
import (
"bytes"
"encoding/binary"
"fmt"
mathbig "math/big"
"golang.org/x/crypto/sha3"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
gocrypto "github.com/filecoin-project/go-crypto"
"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/v8/evm"
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
typescrypto "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
type EthTx struct {
ChainID EthInt `json:"chainId"`
Nonce EthInt `json:"nonce"`
Hash EthHash `json:"hash"`
BlockHash EthHash `json:"blockHash"`
BlockNumber EthInt `json:"blockNumber"`
TransactionIndex EthInt `json:"transacionIndex"`
From EthAddress `json:"from"`
To *EthAddress `json:"to"`
Value EthBigInt `json:"value"`
Type EthInt `json:"type"`
Input EthBytes `json:"input"`
Gas EthInt `json:"gas"`
GasLimit *EthInt `json:"gasLimit,omitempty"`
MaxFeePerGas EthBigInt `json:"maxFeePerGas"`
MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"`
V EthBytes `json:"v"`
R EthBytes `json:"r"`
S EthBytes `json:"s"`
}
type EthTxArgs struct {
ChainID int `json:"chainId"`
Nonce int `json:"nonce"`
To *EthAddress `json:"to"`
Value big.Int `json:"value"`
MaxFeePerGas big.Int `json:"maxFeePerGas"`
MaxPriorityFeePerGas big.Int `json:"maxPrioritiyFeePerGas"`
GasLimit int `json:"gasLimit"`
Input []byte `json:"input"`
V []byte `json:"v"`
R []byte `json:"r"`
S []byte `json:"s"`
}
func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
var to *EthAddress
params := msg.Params
if msg.To == builtintypes.InitActorAddr {
to = nil
var exec init8.ExecParams
reader := bytes.NewReader(msg.Params)
if err := exec.UnmarshalCBOR(reader); err != nil {
return EthTxArgs{}, err
}
var evmParams evm.ConstructorParams
reader1 := bytes.NewReader(exec.ConstructorParams)
if err := evmParams.UnmarshalCBOR(reader1); err != nil {
return EthTxArgs{}, err
}
params = evmParams.Bytecode
} else {
addr, err := EthAddressFromFilecoinIDAddress(msg.To)
if err != nil {
return EthTxArgs{}, nil
}
to = &addr
}
return EthTxArgs{
ChainID: build.Eip155ChainId,
Nonce: int(msg.Nonce),
To: to,
Value: msg.Value,
Input: params,
MaxFeePerGas: msg.GasFeeCap,
MaxPriorityFeePerGas: msg.GasPremium,
GasLimit: int(msg.GasLimit),
}, nil
}
func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
from, err := tx.Sender()
if err != nil {
return nil, err
}
var to address.Address
var params []byte
if tx.To == nil && tx.Input == nil {
return nil, fmt.Errorf("to and input cannot both be empty")
}
if tx.To == nil {
// this is a contract creation
to = builtintypes.InitActorAddr
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
Bytecode: tx.Input,
InputData: []byte{},
})
if err != nil {
return nil, fmt.Errorf("failed to serialize constructor params: %w", err)
}
evmActorCid, ok := actors.GetActorCodeID(actors.Version8, "evm")
if !ok {
return nil, fmt.Errorf("failed to lookup evm actor code CID")
}
params, err = actors.SerializeParams(&init8.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, err
}
to = addr
params = tx.Input
}
msg := &types.Message{
Nonce: uint64(tx.Nonce),
From: from,
To: to,
Value: tx.Value,
Method: 2,
Params: params,
GasLimit: int64(tx.GasLimit),
GasFeeCap: tx.MaxFeePerGas,
GasPremium: tx.MaxPriorityFeePerGas,
}
sig, err := tx.Signature()
if err != nil {
return nil, err
}
signedMsg := types.SignedMessage{
Message: *msg,
Signature: *sig,
}
return &signedMsg, nil
}
func (tx *EthTxArgs) HashedOriginalRlpMsg() ([]byte, error) {
msg, err := tx.OriginalRlpMsg()
if err != nil {
return nil, err
}
hasher := sha3.NewLegacyKeccak256()
hasher.Write(msg)
hash := hasher.Sum(nil)
return hash, nil
}
func (tx *EthTxArgs) OriginalRlpMsg() ([]byte, error) {
chainId, err := formatInt(tx.ChainID)
if err != nil {
return nil, err
}
nonce, err := formatInt(tx.Nonce)
if err != nil {
return nil, err
}
maxPriorityFeePerGas, err := formatBigInt(tx.MaxPriorityFeePerGas)
if err != nil {
return nil, err
}
maxFeePerGas, err := formatBigInt(tx.MaxFeePerGas)
if err != nil {
return nil, err
}
gasLimit, err := formatInt(tx.GasLimit)
if err != nil {
return nil, err
}
value, err := formatBigInt(tx.Value)
if err != nil {
return nil, err
}
res := []interface{}{
chainId,
nonce,
maxPriorityFeePerGas,
maxFeePerGas,
gasLimit,
formatEthAddr(tx.To),
value,
tx.Input,
[]interface{}{}, // access list
}
encoded, err := EncodeRLP(res)
if err != nil {
return nil, err
}
return append([]byte{0x02}, encoded...), nil
}
func (tx *EthTxArgs) Signature() (*typescrypto.Signature, error) {
if tx.V == nil || tx.R == nil || tx.S == nil {
return nil, fmt.Errorf("one of V, R, or S is nil")
}
sig := append([]byte{}, tx.R...)
sig = append(sig, tx.S...)
sig = append(sig, tx.V...)
if len(sig) != 65 {
return nil, fmt.Errorf("signature is not 65 bytes")
}
return &typescrypto.Signature{
Type: typescrypto.SigTypeDelegated, Data: sig,
}, nil
}
func (tx *EthTxArgs) Sender() (address.Address, error) {
msg, err := tx.OriginalRlpMsg()
if err != nil {
return address.Undef, err
}
hasher := sha3.NewLegacyKeccak256()
hasher.Write(msg)
hash := hasher.Sum(nil)
sig, err := tx.Signature()
if err != nil {
return address.Undef, err
}
pubk, err := gocrypto.EcRecover(hash, sig.Data)
if err != nil {
return address.Undef, err
}
return address.NewSecp256k1Address(pubk)
}
func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
if data[0] != 2 {
return nil, xerrors.Errorf("not an EIP-1559 transaction: first byte is not 2")
}
d, err := DecodeRLP(data[1:])
if err != nil {
return nil, err
}
decoded, ok := d.([]interface{})
if !ok {
return nil, xerrors.Errorf("not an EIP-1559 transaction: decoded data is not a list")
}
if len(decoded) != 9 && len(decoded) != 12 {
return nil, xerrors.Errorf("not an EIP-1559 transaction: should have 6 or 9 elements in the list")
}
chainId, err := parseInt(decoded[0])
if err != nil {
return nil, err
}
nonce, err := parseInt(decoded[1])
if err != nil {
return nil, err
}
maxPriorityFeePerGas, err := parseBigInt(decoded[2])
if err != nil {
return nil, err
}
maxFeePerGas, err := parseBigInt(decoded[3])
if err != nil {
return nil, err
}
gasLimit, err := parseInt(decoded[4])
if err != nil {
return nil, err
}
to, err := parseEthAddr(decoded[5])
if err != nil {
return nil, err
}
value, err := parseBigInt(decoded[6])
if err != nil {
return nil, err
}
input, err := parseBytes(decoded[7])
if err != nil {
return nil, err
}
accessList, ok := decoded[8].([]interface{})
if !ok || (ok && len(accessList) != 0) {
return nil, fmt.Errorf("access list should be an empty list")
}
V, err := parseBytes(decoded[9])
if err != nil {
return nil, err
}
if len(V) == 0 {
V = []byte{0}
}
R, err := parseBytes(decoded[10])
if err != nil {
return nil, err
}
S, err := parseBytes(decoded[11])
if err != nil {
return nil, err
}
args := EthTxArgs{
ChainID: chainId,
Nonce: nonce,
To: to,
MaxPriorityFeePerGas: maxPriorityFeePerGas,
MaxFeePerGas: maxFeePerGas,
GasLimit: gasLimit,
Value: value,
Input: input,
R: padLeadingZeros(R, 32),
S: padLeadingZeros(S, 32),
V: V,
}
return &args, nil
}
func ParseEthTxArgs(data []byte) (*EthTxArgs, error) {
if data[0] > 0x7f {
// legacy transaction
return nil, xerrors.Errorf("legacy transaction is not supported")
} else if data[0] == 1 {
// EIP-2930
return nil, xerrors.Errorf("EIP-2930 transaction is not supported")
} else if data[0] == 2 {
// EIP-1559
return parseEip1559Tx(data)
}
return nil, xerrors.Errorf("unsupported transaction type")
}
func padLeadingZeros(data []byte, length int) []byte {
if len(data) >= length {
return data
}
zeros := make([]byte, length-len(data))
return append(zeros, data...)
}
func removeLeadingZeros(data []byte) []byte {
firstNonZeroIndex := len(data)
for i, b := range data {
if b > 0 {
firstNonZeroIndex = i
break
}
}
return data[firstNonZeroIndex:]
}
func formatInt(val int) ([]byte, error) {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, int64(val))
if err != nil {
return nil, err
}
return removeLeadingZeros(buf.Bytes()), nil
}
func formatEthAddr(addr *EthAddress) []byte {
if addr == nil {
return nil
}
return addr[:]
}
func formatBigInt(val big.Int) ([]byte, error) {
b, err := val.Bytes()
if err != nil {
return nil, err
}
return removeLeadingZeros(b), nil
}
func parseInt(v interface{}) (int, error) {
data, ok := v.([]byte)
if !ok {
return 0, xerrors.Errorf("cannot parse interface to int: input is not a byte array")
}
if len(data) == 0 {
return 0, nil
}
if len(data) > 8 {
return 0, xerrors.Errorf("cannot parse interface to int: length is more than 8 bytes")
}
var value int64
r := bytes.NewReader(append(make([]byte, 8-len(data)), data...))
if err := binary.Read(r, binary.BigEndian, &value); err != nil {
return 0, xerrors.Errorf("cannot parse interface to EthInt: %w", err)
}
return int(value), nil
}
func parseBigInt(v interface{}) (big.Int, error) {
data, ok := v.([]byte)
if !ok {
return big.Zero(), xerrors.Errorf("cannot parse interface to big.Int: input is not a byte array")
}
if len(data) == 0 {
return big.Zero(), nil
}
var b mathbig.Int
b.SetBytes(data)
return big.NewFromGo(&b), nil
}
func parseBytes(v interface{}) ([]byte, error) {
val, ok := v.([]byte)
if !ok {
return nil, xerrors.Errorf("cannot parse interface into bytes: input is not a byte array")
}
return val, nil
}
func parseEthAddr(v interface{}) (*EthAddress, error) {
b, err := parseBytes(v)
if err != nil {
return nil, err
}
if b == nil || len(b) == 0 {
return nil, nil
}
addr, err := EthAddressFromBytes(b)
if err != nil {
return nil, err
}
return &addr, nil
}

File diff suppressed because one or more lines are too long

View File

@ -24,6 +24,9 @@ import (
type EthInt int64 type EthInt int64
func (e EthInt) MarshalJSON() ([]byte, error) { func (e EthInt) MarshalJSON() ([]byte, error) {
if e == 0 {
return json.Marshal("0x0")
}
return json.Marshal(fmt.Sprintf("0x%x", e)) return json.Marshal(fmt.Sprintf("0x%x", e))
} }
@ -75,8 +78,14 @@ func (e *EthBigInt) UnmarshalJSON(b []byte) error {
type EthBytes []byte type EthBytes []byte
func (e EthBytes) MarshalJSON() ([]byte, error) { func (e EthBytes) MarshalJSON() ([]byte, error) {
encoded := "0x" + hex.EncodeToString(e) if len(e) == 0 {
return json.Marshal(encoded) return json.Marshal("0x00")
}
s := hex.EncodeToString(e)
if len(s)%2 == 1 {
s = "0" + s
}
return json.Marshal("0x" + s)
} }
func (e *EthBytes) UnmarshalJSON(b []byte) error { func (e *EthBytes) UnmarshalJSON(b []byte) error {
@ -144,33 +153,13 @@ func NewEthBlock() EthBlock {
} }
} }
type EthTx struct {
ChainID EthInt `json:"chainId"`
Nonce uint64 `json:"nonce"`
Hash EthHash `json:"hash"`
BlockHash EthHash `json:"blockHash"`
BlockNumber EthInt `json:"blockNumber"`
TransactionIndex EthInt `json:"transacionIndex"`
From EthAddress `json:"from"`
To *EthAddress `json:"to"`
Value EthBigInt `json:"value"`
Type EthInt `json:"type"`
Input EthBytes `json:"input"`
Gas EthInt `json:"gas"`
MaxFeePerGas EthBigInt `json:"maxFeePerGas"`
MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"`
V EthBigInt `json:"v"`
R EthBigInt `json:"r"`
S EthBigInt `json:"s"`
}
type EthCall struct { type EthCall struct {
From EthAddress `json:"from"` From EthAddress `json:"from"`
To EthAddress `json:"to"` To *EthAddress `json:"to"`
Gas EthInt `json:"gas"` Gas EthInt `json:"gas"`
GasPrice EthBigInt `json:"gasPrice"` GasPrice EthBigInt `json:"gasPrice"`
Value EthBigInt `json:"value"` Value EthBigInt `json:"value"`
Data EthBytes `json:"data"` Data EthBytes `json:"data"`
} }
func (c *EthCall) UnmarshalJSON(b []byte) error { func (c *EthCall) UnmarshalJSON(b []byte) error {
@ -186,7 +175,7 @@ func (c *EthCall) UnmarshalJSON(b []byte) error {
type EthTxReceipt struct { type EthTxReceipt struct {
TransactionHash EthHash `json:"transactionHash"` TransactionHash EthHash `json:"transactionHash"`
TransactionIndex EthInt `json:"transacionIndex"` TransactionIndex EthInt `json:"transactionIndex"`
BlockHash EthHash `json:"blockHash"` BlockHash EthHash `json:"blockHash"`
BlockNumber EthInt `json:"blockNumber"` BlockNumber EthInt `json:"blockNumber"`
From EthAddress `json:"from"` From EthAddress `json:"from"`
@ -199,6 +188,8 @@ type EthTxReceipt struct {
CumulativeGasUsed EthInt `json:"cumulativeGasUsed"` CumulativeGasUsed EthInt `json:"cumulativeGasUsed"`
GasUsed EthInt `json:"gasUsed"` GasUsed EthInt `json:"gasUsed"`
EffectiveGasPrice EthBigInt `json:"effectiveGasPrice"` EffectiveGasPrice EthBigInt `json:"effectiveGasPrice"`
LogsBloom EthBytes `json:"logsBloom"`
Logs []string `json:"logs"`
} }
func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxReceipt, error) { func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxReceipt, error) {
@ -210,6 +201,8 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec
From: tx.From, From: tx.From,
To: tx.To, To: tx.To,
StateRoot: EmptyEthHash, StateRoot: EmptyEthHash,
LogsBloom: []byte{0},
Logs: []string{},
} }
contractAddr, err := CheckContractCreation(lookup) contractAddr, err := CheckContractCreation(lookup)
@ -318,6 +311,15 @@ func EthAddressFromHex(s string) (EthAddress, error) {
return h, nil return h, nil
} }
func EthAddressFromBytes(b []byte) (EthAddress, error) {
var a EthAddress
if len(b) != ETH_ADDRESS_LENGTH {
return EthAddress{}, xerrors.Errorf("cannot initiate a new EthAddress: incorrect input length")
}
copy(a[:], b[:])
return a, nil
}
type EthHash [ETH_HASH_LENGTH]byte type EthHash [ETH_HASH_LENGTH]byte
func (h EthHash) MarshalJSON() ([]byte, error) { func (h EthHash) MarshalJSON() ([]byte, error) {

View File

@ -1,4 +1,4 @@
//stm: #unit // stm: #unit
package api package api
import ( import (

View File

@ -982,18 +982,18 @@ func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call {
} }
// EthEstimateGas mocks base method. // EthEstimateGas mocks base method.
func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 api.EthCall, arg2 string) (api.EthInt, error) { func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 api.EthCall) (api.EthInt, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1, arg2) ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1)
ret0, _ := ret[0].(api.EthInt) ret0, _ := ret[0].(api.EthInt)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// EthEstimateGas indicates an expected call of EthEstimateGas. // EthEstimateGas indicates an expected call of EthEstimateGas.
func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1, arg2 interface{}) *gomock.Call { func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthEstimateGas", reflect.TypeOf((*MockFullNode)(nil).EthEstimateGas), arg0, arg1, arg2) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthEstimateGas", reflect.TypeOf((*MockFullNode)(nil).EthEstimateGas), arg0, arg1)
} }
// EthGasPrice mocks base method. // EthGasPrice mocks base method.
@ -1042,7 +1042,7 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockByHash(arg0, arg1, arg2 interface
} }
// EthGetBlockByNumber mocks base method. // EthGetBlockByNumber mocks base method.
func (m *MockFullNode) EthGetBlockByNumber(arg0 context.Context, arg1 api.EthInt, arg2 bool) (api.EthBlock, error) { func (m *MockFullNode) EthGetBlockByNumber(arg0 context.Context, arg1 string, arg2 bool) (api.EthBlock, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthGetBlockByNumber", arg0, arg1, arg2) ret := m.ctrl.Call(m, "EthGetBlockByNumber", arg0, arg1, arg2)
ret0, _ := ret[0].(api.EthBlock) ret0, _ := ret[0].(api.EthBlock)
@ -1147,10 +1147,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockNumberAndIndex(arg0,
} }
// EthGetTransactionByHash mocks base method. // EthGetTransactionByHash mocks base method.
func (m *MockFullNode) EthGetTransactionByHash(arg0 context.Context, arg1 api.EthHash) (api.EthTx, error) { func (m *MockFullNode) EthGetTransactionByHash(arg0 context.Context, arg1 *api.EthHash) (*api.EthTx, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthGetTransactionByHash", arg0, arg1) ret := m.ctrl.Call(m, "EthGetTransactionByHash", arg0, arg1)
ret0, _ := ret[0].(api.EthTx) ret0, _ := ret[0].(*api.EthTx)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1177,10 +1177,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionCount(arg0, arg1, arg2 inte
} }
// EthGetTransactionReceipt mocks base method. // EthGetTransactionReceipt mocks base method.
func (m *MockFullNode) EthGetTransactionReceipt(arg0 context.Context, arg1 api.EthHash) (api.EthTxReceipt, error) { func (m *MockFullNode) EthGetTransactionReceipt(arg0 context.Context, arg1 api.EthHash) (*api.EthTxReceipt, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthGetTransactionReceipt", arg0, arg1) ret := m.ctrl.Call(m, "EthGetTransactionReceipt", arg0, arg1)
ret0, _ := ret[0].(api.EthTxReceipt) ret0, _ := ret[0].(*api.EthTxReceipt)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }

View File

@ -10,12 +10,15 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
blocks "github.com/ipfs/go-block-format" blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/metrics" "github.com/libp2p/go-libp2p/core/metrics"
"github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol" "github.com/libp2p/go-libp2p/core/protocol"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
@ -37,6 +40,7 @@ import (
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/journal/alerting" "github.com/filecoin-project/lotus/journal/alerting"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo/imports" "github.com/filecoin-project/lotus/node/repo/imports"
"github.com/filecoin-project/lotus/storage/pipeline/sealiface" "github.com/filecoin-project/lotus/storage/pipeline/sealiface"
@ -226,7 +230,7 @@ type FullNodeStruct struct {
EthChainId func(p0 context.Context) (EthInt, error) `perm:"read"` EthChainId func(p0 context.Context) (EthInt, error) `perm:"read"`
EthEstimateGas func(p0 context.Context, p1 EthCall, p2 string) (EthInt, error) `perm:"read"` EthEstimateGas func(p0 context.Context, p1 EthCall) (EthInt, error) `perm:"read"`
EthGasPrice func(p0 context.Context) (EthBigInt, error) `perm:"read"` EthGasPrice func(p0 context.Context) (EthBigInt, error) `perm:"read"`
@ -234,7 +238,7 @@ type FullNodeStruct struct {
EthGetBlockByHash func(p0 context.Context, p1 EthHash, p2 bool) (EthBlock, error) `perm:"read"` EthGetBlockByHash func(p0 context.Context, p1 EthHash, p2 bool) (EthBlock, error) `perm:"read"`
EthGetBlockByNumber func(p0 context.Context, p1 EthInt, p2 bool) (EthBlock, error) `perm:"read"` EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (EthBlock, error) `perm:"read"`
EthGetBlockTransactionCountByHash func(p0 context.Context, p1 EthHash) (EthInt, error) `perm:"read"` EthGetBlockTransactionCountByHash func(p0 context.Context, p1 EthHash) (EthInt, error) `perm:"read"`
@ -248,11 +252,11 @@ type FullNodeStruct struct {
EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 EthInt, p2 EthInt) (EthTx, error) `perm:"read"` EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 EthInt, p2 EthInt) (EthTx, error) `perm:"read"`
EthGetTransactionByHash func(p0 context.Context, p1 EthHash) (EthTx, error) `perm:"read"` EthGetTransactionByHash func(p0 context.Context, p1 *EthHash) (*EthTx, error) `perm:"read"`
EthGetTransactionCount func(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) `perm:"read"` EthGetTransactionCount func(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) `perm:"read"`
EthGetTransactionReceipt func(p0 context.Context, p1 EthHash) (EthTxReceipt, error) `perm:"read"` EthGetTransactionReceipt func(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) `perm:"read"`
EthMaxPriorityFeePerGas func(p0 context.Context) (EthBigInt, error) `perm:"read"` EthMaxPriorityFeePerGas func(p0 context.Context) (EthBigInt, error) `perm:"read"`
@ -1881,14 +1885,14 @@ func (s *FullNodeStub) EthChainId(p0 context.Context) (EthInt, error) {
return *new(EthInt), ErrNotSupported return *new(EthInt), ErrNotSupported
} }
func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 EthCall, p2 string) (EthInt, error) { func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 EthCall) (EthInt, error) {
if s.Internal.EthEstimateGas == nil { if s.Internal.EthEstimateGas == nil {
return *new(EthInt), ErrNotSupported return *new(EthInt), ErrNotSupported
} }
return s.Internal.EthEstimateGas(p0, p1, p2) return s.Internal.EthEstimateGas(p0, p1)
} }
func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 EthCall, p2 string) (EthInt, error) { func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 EthCall) (EthInt, error) {
return *new(EthInt), ErrNotSupported return *new(EthInt), ErrNotSupported
} }
@ -1925,14 +1929,14 @@ func (s *FullNodeStub) EthGetBlockByHash(p0 context.Context, p1 EthHash, p2 bool
return *new(EthBlock), ErrNotSupported return *new(EthBlock), ErrNotSupported
} }
func (s *FullNodeStruct) EthGetBlockByNumber(p0 context.Context, p1 EthInt, p2 bool) (EthBlock, error) { func (s *FullNodeStruct) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (EthBlock, error) {
if s.Internal.EthGetBlockByNumber == nil { if s.Internal.EthGetBlockByNumber == nil {
return *new(EthBlock), ErrNotSupported return *new(EthBlock), ErrNotSupported
} }
return s.Internal.EthGetBlockByNumber(p0, p1, p2) return s.Internal.EthGetBlockByNumber(p0, p1, p2)
} }
func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 EthInt, p2 bool) (EthBlock, error) { func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (EthBlock, error) {
return *new(EthBlock), ErrNotSupported return *new(EthBlock), ErrNotSupported
} }
@ -2002,15 +2006,15 @@ func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context
return *new(EthTx), ErrNotSupported return *new(EthTx), ErrNotSupported
} }
func (s *FullNodeStruct) EthGetTransactionByHash(p0 context.Context, p1 EthHash) (EthTx, error) { func (s *FullNodeStruct) EthGetTransactionByHash(p0 context.Context, p1 *EthHash) (*EthTx, error) {
if s.Internal.EthGetTransactionByHash == nil { if s.Internal.EthGetTransactionByHash == nil {
return *new(EthTx), ErrNotSupported return nil, ErrNotSupported
} }
return s.Internal.EthGetTransactionByHash(p0, p1) return s.Internal.EthGetTransactionByHash(p0, p1)
} }
func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 EthHash) (EthTx, error) { func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 *EthHash) (*EthTx, error) {
return *new(EthTx), ErrNotSupported return nil, ErrNotSupported
} }
func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) { func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) {
@ -2024,15 +2028,15 @@ func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 EthAddress,
return *new(EthInt), ErrNotSupported return *new(EthInt), ErrNotSupported
} }
func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (EthTxReceipt, error) { func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) {
if s.Internal.EthGetTransactionReceipt == nil { if s.Internal.EthGetTransactionReceipt == nil {
return *new(EthTxReceipt), ErrNotSupported return nil, ErrNotSupported
} }
return s.Internal.EthGetTransactionReceipt(p0, p1) return s.Internal.EthGetTransactionReceipt(p0, p1)
} }
func (s *FullNodeStub) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (EthTxReceipt, error) { func (s *FullNodeStub) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) {
return *new(EthTxReceipt), ErrNotSupported return nil, ErrNotSupported
} }
func (s *FullNodeStruct) EthMaxPriorityFeePerGas(p0 context.Context) (EthBigInt, error) { func (s *FullNodeStruct) EthMaxPriorityFeePerGas(p0 context.Context) (EthBigInt, error) {

176
api/rlp.go Normal file
View File

@ -0,0 +1,176 @@
package api
import (
"bytes"
"encoding/binary"
"fmt"
"golang.org/x/xerrors"
)
func EncodeRLP(val interface{}) ([]byte, error) {
return encodeRLP(val)
}
func encodeRLPListItems(list []interface{}) (result []byte, err error) {
res := []byte{}
for _, elem := range list {
encoded, err := encodeRLP(elem)
if err != nil {
return nil, err
}
res = append(res, encoded...)
}
return res, nil
}
func encodeLength(length int) (lenInBytes []byte, err error) {
if length == 0 {
return nil, fmt.Errorf("cannot encode length: length should be larger than 0")
}
buf := new(bytes.Buffer)
err = binary.Write(buf, binary.BigEndian, int64(length))
if err != nil {
return nil, err
}
firstNonZeroIndex := len(buf.Bytes()) - 1
for i, b := range buf.Bytes() {
if b != 0 {
firstNonZeroIndex = i
break
}
}
res := buf.Bytes()[firstNonZeroIndex:]
return res, nil
}
func encodeRLP(val interface{}) ([]byte, error) {
if data, ok := val.([]byte); ok {
if len(data) == 1 && data[0] <= 0x7f {
return data, nil
} else if len(data) <= 55 {
prefix := byte(0x80 + len(data))
return append([]byte{prefix}, data...), nil
} else {
lenInBytes, err := encodeLength(len(data))
if err != nil {
return nil, err
}
prefix := byte(0xb7 + len(lenInBytes))
return append(
[]byte{prefix},
append(lenInBytes, data...)...,
), nil
}
} else if data, ok := val.([]interface{}); ok {
encodedList, err := encodeRLPListItems(data)
if err != nil {
return nil, err
}
if len(encodedList) <= 55 {
prefix := byte(0xc0 + len(encodedList))
return append(
[]byte{prefix},
encodedList...,
), nil
}
lenInBytes, err := encodeLength(len(encodedList))
if err != nil {
return nil, err
}
prefix := byte(0xf7 + len(lenInBytes))
return append(
[]byte{prefix},
append(lenInBytes, encodedList...)...,
), nil
}
return nil, fmt.Errorf("input data should either be a list or a byte array")
}
func DecodeRLP(data []byte) (interface{}, error) {
res, consumed, err := decodeRLP(data)
if err != nil {
return nil, err
}
if consumed != len(data) {
return nil, xerrors.Errorf("invalid rlp data: length %d, consumed %d", len(data), consumed)
}
return res, nil
}
func decodeRLP(data []byte) (res interface{}, consumed int, err error) {
if len(data) == 0 {
return data, 0, xerrors.Errorf("invalid rlp data: data cannot be empty")
}
if data[0] >= 0xf8 {
listLenInBytes := int(data[0]) - 0xf7
listLen, err := decodeLength(data[1:], listLenInBytes)
if err != nil {
return nil, 0, err
}
if 1+listLenInBytes+listLen > len(data) {
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
}
result, err := decodeListElems(data[1+listLenInBytes:], listLen)
return result, 1 + listLenInBytes + listLen, err
} else if data[0] >= 0xc0 {
length := int(data[0]) - 0xc0
result, err := decodeListElems(data[1:], length)
return result, 1 + length, err
} else if data[0] >= 0xb8 {
strLenInBytes := int(data[0]) - 0xb7
strLen, err := decodeLength(data[1:], strLenInBytes)
if err != nil {
return nil, 0, err
}
totalLen := 1 + strLenInBytes + strLen
if totalLen > len(data) {
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string")
}
return data[1+strLenInBytes : totalLen], totalLen, nil
} else if data[0] >= 0x80 {
length := int(data[0]) - 0x80
if 1+length > len(data) {
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string")
}
return data[1 : 1+length], 1 + length, nil
}
return []byte{data[0]}, 1, nil
}
func decodeLength(data []byte, lenInBytes int) (length int, err error) {
if lenInBytes > len(data) || lenInBytes > 8 {
return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list length")
}
var decodedLength int64
r := bytes.NewReader(append(make([]byte, 8-lenInBytes), data[:lenInBytes]...))
if err := binary.Read(r, binary.BigEndian, &decodedLength); err != nil {
return 0, xerrors.Errorf("invalid rlp data: cannot parse string length: %w", err)
}
if lenInBytes+int(decodedLength) > len(data) {
return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
}
return int(decodedLength), nil
}
func decodeListElems(data []byte, length int) (res []interface{}, err error) {
totalConsumed := 0
result := []interface{}{}
// set a limit to make sure it doesn't loop infinitely
for i := 0; totalConsumed < length && i < 5000; i++ {
elem, consumed, err := decodeRLP(data[totalConsumed:])
if err != nil {
return nil, xerrors.Errorf("invalid rlp data: cannot decode list element: %w", err)
}
totalConsumed += consumed
result = append(result, elem)
}
if totalConsumed != length {
return nil, xerrors.Errorf("invalid rlp data: incorrect list length")
}
return result, nil
}

175
api/rlp_test.go Normal file
View File

@ -0,0 +1,175 @@
package api
import (
"encoding/hex"
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestEncode(t *testing.T) {
testcases := []TestCase{
{[]byte(""), mustDecodeHex("0x80")},
{mustDecodeHex("0x01"), mustDecodeHex("0x01")},
{mustDecodeHex("0xaa"), mustDecodeHex("0x81aa")},
{mustDecodeHex("0x0402"), mustDecodeHex("0x820402")},
{
[]interface{}{},
mustDecodeHex("0xc0"),
},
{
mustDecodeHex("0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
mustDecodeHex("0xb83cabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
},
{
mustDecodeHex("0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
mustDecodeHex("0xb8aaabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
},
{
[]interface{}{
mustDecodeHex("0xaaaa"),
mustDecodeHex("0xbbbb"),
mustDecodeHex("0xcccc"),
mustDecodeHex("0xdddd"),
},
mustDecodeHex("0xcc82aaaa82bbbb82cccc82dddd"),
},
{
[]interface{}{
mustDecodeHex("0xaaaaaaaaaaaaaaaaaaaa"),
mustDecodeHex("0xbbbbbbbbbbbbbbbbbbbb"),
[]interface{}{
mustDecodeHex("0xc1c1c1c1c1c1c1c1c1c1"),
mustDecodeHex("0xc2c2c2c2c2c2c2c2c2c2"),
mustDecodeHex("0xc3c3c3c3c3c3c3c3c3c3"),
},
mustDecodeHex("0xdddddddddddddddddddd"),
mustDecodeHex("0xeeeeeeeeeeeeeeeeeeee"),
mustDecodeHex("0xffffffffffffffffffff"),
},
mustDecodeHex("0xf8598aaaaaaaaaaaaaaaaaaaaa8abbbbbbbbbbbbbbbbbbbbe18ac1c1c1c1c1c1c1c1c1c18ac2c2c2c2c2c2c2c2c2c28ac3c3c3c3c3c3c3c3c3c38adddddddddddddddddddd8aeeeeeeeeeeeeeeeeeeee8affffffffffffffffffff"),
},
}
for _, tc := range testcases {
result, err := EncodeRLP(tc.Input)
require.Nil(t, err)
require.Equal(t, tc.Output.([]byte), result)
}
}
func TestDecodeString(t *testing.T) {
testcases := []TestCase{
{"0x00", "0x00"},
{"0x80", "0x"},
{"0x0f", "0x0f"},
{"0x81aa", "0xaa"},
{"0x820400", "0x0400"},
{"0xb83cabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
"0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"},
}
for _, tc := range testcases {
input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1))
require.Nil(t, err)
output, err := hex.DecodeString(strings.Replace(tc.Output.(string), "0x", "", -1))
require.Nil(t, err)
result, err := DecodeRLP(input)
require.Nil(t, err)
require.Equal(t, output, result.([]byte))
}
}
func mustDecodeHex(s string) []byte {
d, err := hex.DecodeString(strings.Replace(s, "0x", "", -1))
if err != nil {
panic(fmt.Errorf("err must be nil: %w", err))
}
return d
}
func TestDecodeList(t *testing.T) {
testcases := []TestCase{
{"0xc0", []interface{}{}},
{"0xc100", []interface{}{[]byte{0}}},
{"0xc3000102", []interface{}{[]byte{0}, []byte{1}, []byte{2}}},
{"0xc4000181aa", []interface{}{[]byte{0}, []byte{1}, []byte{0xaa}}},
{"0xc6000181aa81ff", []interface{}{[]byte{0}, []byte{1}, []byte{0xaa}, []byte{0xff}}},
{"0xf8428aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd",
[]interface{}{
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
},
},
{"0xf1030185012a05f2008504a817c800825208942b87d1cb599bc2a606db9a0169fcec96af04ad3a880de0b6b3a764000080c0",
[]interface{}{
[]byte{3},
[]byte{1},
mustDecodeHex("0x012a05f200"),
mustDecodeHex("0x04a817c800"),
mustDecodeHex("0x5208"),
mustDecodeHex("0x2b87d1CB599Bc2a606Db9A0169fcEc96Af04ad3a"),
mustDecodeHex("0x0de0b6b3a7640000"),
[]byte{},
[]interface{}{},
}},
}
for _, tc := range testcases {
input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1))
require.Nil(t, err)
result, err := DecodeRLP(input)
require.Nil(t, err)
fmt.Println(result)
r := result.([]interface{})
require.Equal(t, len(tc.Output.([]interface{})), len(r))
for i, v := range r {
require.Equal(t, tc.Output.([]interface{})[i], v)
}
}
}
func TestDecodeEncodeTx(t *testing.T) {
testcases := [][]byte{
mustDecodeHex("0xdc82013a0185012a05f2008504a817c8008080872386f26fc1000000c0"),
mustDecodeHex("0xf85f82013a0185012a05f2008504a817c8008080872386f26fc1000000c001a027fa36fb9623e4d71fcdd7f7dce71eb814c9560dcf3908c1719386e2efd122fba05fb4e4227174eeb0ba84747a4fb883c8d4e0fdb129c4b1f42e90282c41480234"),
mustDecodeHex("0xf9061c82013a0185012a05f2008504a817c8008080872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0c4e9477f57c6848b2f1ea73a14809c1f44529d20763c947f3ac8ffd3d1629d93a011485a215457579bb13ac7b53bb9d6804763ae6fe5ce8ddd41642cea55c9a09a"),
mustDecodeHex("0xf9063082013a0185012a05f2008504a817c8008094025b594a4f1c4888cafcfaf2bb24ed95507749e0872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0fe38720928596f9e9dfbf891d00311638efce3713f03cdd67b212ecbbcf18f29a05993e656c0b35b8a580da6aff7c89b3d3e8b1c6f83a7ce09473c0699a8500b9c"),
}
for _, tc := range testcases {
decoded, err := DecodeRLP(tc)
require.Nil(t, err)
encoded, err := EncodeRLP(decoded)
require.Nil(t, err)
require.Equal(t, tc, encoded)
}
}
func TestDecodeError(t *testing.T) {
testcases := [][]byte{
mustDecodeHex("0xdc82013a0185012a05f2008504a817c8008080872386f26fc1000000"),
mustDecodeHex("0xdc013a01012a05f2008504a817c8008080872386f26fc1000000"),
mustDecodeHex("0xdc82013a0185012a05f28504a817c08080872386f26fc1000000"),
mustDecodeHex("0xdc82013a0185012a05f504a817c080872386ffc1000000"),
mustDecodeHex("0x013a018505f2008504a817c8008080872386f26fc1000000"),
}
for _, tc := range testcases {
_, err := DecodeRLP(tc)
require.NotNil(t, err, hex.EncodeToString(tc))
}
}

View File

@ -26,6 +26,7 @@ import (
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof"
"github.com/filecoin-project/lotus/api"
bstore "github.com/filecoin-project/lotus/blockstore" bstore "github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
@ -543,7 +544,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
smArr := blockadt.MakeEmptyArray(tmpstore) smArr := blockadt.MakeEmptyArray(tmpstore)
for i, m := range b.SecpkMessages { for i, m := range b.SecpkMessages {
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version14 { if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version14 {
if m.Signature.Type != crypto.SigTypeSecp256k1 { if m.Signature.Type != crypto.SigTypeSecp256k1 && m.Signature.Type != crypto.SigTypeDelegated {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err) return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
} }
} }
@ -559,7 +560,20 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
return xerrors.Errorf("failed to resolve key addr: %w", err) return xerrors.Errorf("failed to resolve key addr: %w", err)
} }
if err := sigs.Verify(&m.Signature, kaddr, m.Message.Cid().Bytes()); err != nil { digest := m.Message.Cid().Bytes()
if m.Signature.Type == crypto.SigTypeDelegated {
txArgs, err := api.NewEthTxArgsFromMessage(&m.Message)
if err != nil {
return err
}
msg, err := txArgs.OriginalRlpMsg()
if err != nil {
return err
}
digest = msg
}
if err := sigs.Verify(&m.Signature, kaddr, digest); err != nil {
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err) return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
} }

View File

@ -65,7 +65,7 @@ func (filec *FilecoinEC) CreateBlock(ctx context.Context, w api.Wallet, bt *api.
} }
blsMsgCids = append(blsMsgCids, c) blsMsgCids = append(blsMsgCids, c)
} else if msg.Signature.Type == crypto.SigTypeSecp256k1 { } else if msg.Signature.Type == crypto.SigTypeSecp256k1 || msg.Signature.Type == crypto.SigTypeDelegated {
c, err := filec.sm.ChainStore().PutMessage(ctx, msg) c, err := filec.sm.ChainStore().PutMessage(ctx, msg)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -3,6 +3,7 @@ package messagepool
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math" "math"
@ -770,6 +771,16 @@ func sigCacheKey(m *types.SignedMessage) (string, error) {
return string(hashCache[:]), nil return string(hashCache[:]), nil
case crypto.SigTypeSecp256k1: case crypto.SigTypeSecp256k1:
return string(m.Cid().Bytes()), nil return string(m.Cid().Bytes()), nil
case crypto.SigTypeDelegated:
txArgs, err := api.NewEthTxArgsFromMessage(&m.Message)
if err != nil {
return "", err
}
msg, err := txArgs.HashedOriginalRlpMsg()
if err != nil {
return "", err
}
return hex.EncodeToString(msg), nil
default: default:
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type) return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
} }
@ -787,7 +798,19 @@ func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error {
return nil return nil
} }
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil { if m.Signature.Type == crypto.SigTypeDelegated {
txArgs, err := api.NewEthTxArgsFromMessage(&m.Message)
if err != nil {
return err
}
msg, err := txArgs.OriginalRlpMsg()
if err != nil {
return err
}
if err := sigs.Verify(&m.Signature, m.Message.From, msg); err != nil {
return err
}
} else if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
return err return err
} }

View File

@ -97,7 +97,7 @@ func (sm *selectedMessages) tryToAdd(mc *msgChain) bool {
sm.msgs = append(sm.msgs, mc.msgs...) sm.msgs = append(sm.msgs, mc.msgs...)
sm.blsLimit -= l sm.blsLimit -= l
sm.gasLimit -= mc.gasLimit sm.gasLimit -= mc.gasLimit
} else if mc.sigType == crypto.SigTypeSecp256k1 { } else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
if sm.secpLimit < l { if sm.secpLimit < l {
return false return false
} }
@ -123,7 +123,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
if mc.sigType == crypto.SigTypeBLS { if mc.sigType == crypto.SigTypeBLS {
smMsgLimit = sm.blsLimit smMsgLimit = sm.blsLimit
} else if mc.sigType == crypto.SigTypeSecp256k1 { } else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
smMsgLimit = sm.secpLimit smMsgLimit = sm.secpLimit
} else { } else {
return false return false
@ -174,7 +174,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
if mc.sigType == crypto.SigTypeBLS { if mc.sigType == crypto.SigTypeBLS {
sm.blsLimit -= chainMsgLimit sm.blsLimit -= chainMsgLimit
} else if mc.sigType == crypto.SigTypeSecp256k1 { } else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
sm.secpLimit -= chainMsgLimit sm.secpLimit -= chainMsgLimit
} }
@ -187,7 +187,7 @@ func (sm *selectedMessages) trimChain(mc *msgChain, mp *MessagePool, baseFee typ
if msgLimit > sm.blsLimit { if msgLimit > sm.blsLimit {
msgLimit = sm.blsLimit msgLimit = sm.blsLimit
} }
} else if mc.sigType == crypto.SigTypeSecp256k1 { } else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
if msgLimit > sm.secpLimit { if msgLimit > sm.secpLimit {
msgLimit = sm.secpLimit msgLimit = sm.secpLimit
} }

View File

@ -31,6 +31,7 @@ import (
"github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )

View File

@ -1145,7 +1145,7 @@ func persistMessages(ctx context.Context, bs bstore.Blockstore, bst *exchange.Co
} }
} }
for _, m := range bst.Secpk { for _, m := range bst.Secpk {
if m.Signature.Type != crypto.SigTypeSecp256k1 { if m.Signature.Type != crypto.SigTypeSecp256k1 && m.Signature.Type != crypto.SigTypeDelegated {
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type) return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
} }
//log.Infof("putting secp256k1 message: %s", m.Cid()) //log.Infof("putting secp256k1 message: %s", m.Cid())

View File

@ -39,6 +39,8 @@ func (kt *KeyType) UnmarshalJSON(bb []byte) error {
*kt = KTBLS *kt = KTBLS
case crypto.SigTypeSecp256k1: case crypto.SigTypeSecp256k1:
*kt = KTSecp256k1 *kt = KTSecp256k1
case crypto.SigTypeDelegated:
*kt = KTDelegated
default: default:
return fmt.Errorf("unknown sigtype: %d", bst) return fmt.Errorf("unknown sigtype: %d", bst)
} }
@ -51,6 +53,7 @@ const (
KTBLS KeyType = "bls" KTBLS KeyType = "bls"
KTSecp256k1 KeyType = "secp256k1" KTSecp256k1 KeyType = "secp256k1"
KTSecp256k1Ledger KeyType = "secp256k1-ledger" KTSecp256k1Ledger KeyType = "secp256k1-ledger"
KTDelegated KeyType = "delegated"
) )
// KeyInfo is used for storing keys in KeyStore // KeyInfo is used for storing keys in KeyStore

View File

@ -19,6 +19,7 @@ import (
"github.com/filecoin-project/lotus/chain/vectors" "github.com/filecoin-project/lotus/chain/vectors"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )

View File

@ -111,6 +111,7 @@ var Prices = map[abi.ChainEpoch]Pricelist{
verifySignature: map[crypto.SigType]int64{ verifySignature: map[crypto.SigType]int64{
crypto.SigTypeBLS: 16598605, crypto.SigTypeBLS: 16598605,
crypto.SigTypeSecp256k1: 1637292, crypto.SigTypeSecp256k1: 1637292,
crypto.SigTypeDelegated: 1637292,
}, },
hashingBase: 31355, hashingBase: 31355,

View File

@ -45,7 +45,7 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
} }
switch k.Type { switch k.Type {
case types.KTSecp256k1: case types.KTSecp256k1, types.KTDelegated:
k.Address, err = address.NewSecp256k1Address(k.PublicKey) k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil { if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err) return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
@ -68,6 +68,8 @@ func ActSigType(typ types.KeyType) crypto.SigType {
return crypto.SigTypeBLS return crypto.SigTypeBLS
case types.KTSecp256k1: case types.KTSecp256k1:
return crypto.SigTypeSecp256k1 return crypto.SigTypeSecp256k1
case types.KTDelegated:
return crypto.SigTypeDelegated
default: default:
return crypto.SigTypeUnknown return crypto.SigTypeUnknown
} }

View File

@ -16,7 +16,8 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/chain/wallet/key"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures _ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures _ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
) )

View File

@ -41,6 +41,7 @@ import (
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"

View File

@ -10,6 +10,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )

View File

@ -23,6 +23,7 @@ import (
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/chain/wallet/key"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/lp2p" "github.com/filecoin-project/lotus/node/modules/lp2p"

View File

@ -27,7 +27,8 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/conformance/chaos" "github.com/filecoin-project/lotus/conformance/chaos"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures _ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures _ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
) )

View File

@ -2186,7 +2186,7 @@ Inputs:
[ [
{ {
"from": "0x0707070707070707070707070707070707070707", "from": "0x0707070707070707070707070707070707070707",
"to": "0x0707070707070707070707070707070707070707", "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031",
"gas": "0x5", "gas": "0x5",
"gasPrice": "0x0", "gasPrice": "0x0",
"value": "0x0", "value": "0x0",
@ -2217,13 +2217,12 @@ Inputs:
[ [
{ {
"from": "0x0707070707070707070707070707070707070707", "from": "0x0707070707070707070707070707070707070707",
"to": "0x0707070707070707070707070707070707070707", "to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031",
"gas": "0x5", "gas": "0x5",
"gasPrice": "0x0", "gasPrice": "0x0",
"value": "0x0", "value": "0x0",
"data": "0x07" "data": "0x07"
}, }
"string value"
] ]
``` ```
@ -2302,7 +2301,7 @@ Perms: read
Inputs: Inputs:
```json ```json
[ [
"0x5", "string value",
true true
] ]
``` ```
@ -2412,7 +2411,7 @@ Response:
```json ```json
{ {
"chainId": "0x5", "chainId": "0x5",
"nonce": 42, "nonce": "0x5",
"hash": "0x0707070707070707070707070707070707070707070707070707070707070707", "hash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707", "blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockNumber": "0x5", "blockNumber": "0x5",
@ -2423,11 +2422,12 @@ Response:
"type": "0x5", "type": "0x5",
"input": "0x07", "input": "0x07",
"gas": "0x5", "gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0", "maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0",
"v": "0x0", "v": "0x07",
"r": "0x0", "r": "0x07",
"s": "0x0" "s": "0x07"
} }
``` ```
@ -2448,7 +2448,7 @@ Response:
```json ```json
{ {
"chainId": "0x5", "chainId": "0x5",
"nonce": 42, "nonce": "0x5",
"hash": "0x0707070707070707070707070707070707070707070707070707070707070707", "hash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707", "blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockNumber": "0x5", "blockNumber": "0x5",
@ -2459,11 +2459,12 @@ Response:
"type": "0x5", "type": "0x5",
"input": "0x07", "input": "0x07",
"gas": "0x5", "gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0", "maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0",
"v": "0x0", "v": "0x07",
"r": "0x0", "r": "0x07",
"s": "0x0" "s": "0x07"
} }
``` ```
@ -2475,7 +2476,7 @@ Perms: read
Inputs: Inputs:
```json ```json
[ [
"0x0707070707070707070707070707070707070707070707070707070707070707" "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
] ]
``` ```
@ -2483,7 +2484,7 @@ Response:
```json ```json
{ {
"chainId": "0x5", "chainId": "0x5",
"nonce": 42, "nonce": "0x5",
"hash": "0x0707070707070707070707070707070707070707070707070707070707070707", "hash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707", "blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockNumber": "0x5", "blockNumber": "0x5",
@ -2494,11 +2495,12 @@ Response:
"type": "0x5", "type": "0x5",
"input": "0x07", "input": "0x07",
"gas": "0x5", "gas": "0x5",
"gasLimit": "0x5",
"maxFeePerGas": "0x0", "maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0",
"v": "0x0", "v": "0x07",
"r": "0x0", "r": "0x07",
"s": "0x0" "s": "0x07"
} }
``` ```
@ -2533,7 +2535,7 @@ Response:
```json ```json
{ {
"transactionHash": "0x0707070707070707070707070707070707070707070707070707070707070707", "transactionHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"transacionIndex": "0x5", "transactionIndex": "0x5",
"blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707", "blockHash": "0x0707070707070707070707070707070707070707070707070707070707070707",
"blockNumber": "0x5", "blockNumber": "0x5",
"from": "0x0707070707070707070707070707070707070707", "from": "0x0707070707070707070707070707070707070707",
@ -2543,7 +2545,11 @@ Response:
"contractAddress": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031", "contractAddress": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031",
"cumulativeGasUsed": "0x5", "cumulativeGasUsed": "0x5",
"gasUsed": "0x5", "gasUsed": "0x5",
"effectiveGasPrice": "0x0" "effectiveGasPrice": "0x0",
"logsBloom": "0x07",
"logs": [
"string value"
]
} }
``` ```

View File

@ -25,6 +25,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node/impl/full" "github.com/filecoin-project/lotus/node/impl/full"

2
go.sum
View File

@ -345,6 +345,8 @@ github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27 h1:1/o3al2zThas9rW6xqPKAzjs4q2tiBHaBNBP2sx0Vc4= github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27 h1:1/o3al2zThas9rW6xqPKAzjs4q2tiBHaBNBP2sx0Vc4=
github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo= github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo=
github.com/filecoin-project/go-state-types v0.1.11-0.20220923222823-af1291888ee8 h1:iu/6jTVXyZDN/RBh2M2+K0i1ML+4DxydDJ/Bm7BjhjA=
github.com/filecoin-project/go-state-types v0.1.11-0.20220923222823-af1291888ee8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=

View File

@ -0,0 +1,57 @@
package delegated
import (
"fmt"
"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"
"github.com/filecoin-project/lotus/lib/sigs"
)
type delegatedSigner struct{}
func (delegatedSigner) GenPrivate() ([]byte, error) {
priv, err := gocrypto.GenerateKey()
if err != nil {
return nil, err
}
return priv, nil
}
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 init() {
sigs.RegisterSignature(crypto1.SigTypeDelegated, delegatedSigner{})
}

View File

@ -6,7 +6,7 @@ import (
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto" gocrypto "github.com/filecoin-project/go-crypto"
crypto2 "github.com/filecoin-project/go-state-types/crypto" crypto2 "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
@ -15,7 +15,7 @@ import (
type secpSigner struct{} type secpSigner struct{}
func (secpSigner) GenPrivate() ([]byte, error) { func (secpSigner) GenPrivate() ([]byte, error) {
priv, err := crypto.GenerateKey() priv, err := gocrypto.GenerateKey()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -23,12 +23,12 @@ func (secpSigner) GenPrivate() ([]byte, error) {
} }
func (secpSigner) ToPublic(pk []byte) ([]byte, error) { func (secpSigner) ToPublic(pk []byte) ([]byte, error) {
return crypto.PublicKey(pk), nil return gocrypto.PublicKey(pk), nil
} }
func (secpSigner) Sign(pk []byte, msg []byte) ([]byte, error) { func (secpSigner) Sign(pk []byte, msg []byte) ([]byte, error) {
b2sum := blake2b.Sum256(msg) b2sum := blake2b.Sum256(msg)
sig, err := crypto.Sign(pk, b2sum[:]) sig, err := gocrypto.Sign(pk, b2sum[:])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -38,7 +38,7 @@ func (secpSigner) Sign(pk []byte, msg []byte) ([]byte, error) {
func (secpSigner) Verify(sig []byte, a address.Address, msg []byte) error { func (secpSigner) Verify(sig []byte, a address.Address, msg []byte) error {
b2sum := blake2b.Sum256(msg) b2sum := blake2b.Sum256(msg)
pubk, err := crypto.EcRecover(b2sum[:], sig) pubk, err := gocrypto.EcRecover(b2sum[:], sig)
if err != nil { if err != nil {
return err return err
} }

View File

@ -30,6 +30,7 @@ import (
"github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/lib/peermgr" "github.com/filecoin-project/lotus/lib/peermgr"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/markets/storageadapter" "github.com/filecoin-project/lotus/markets/storageadapter"
"github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/config"

View File

@ -2,18 +2,25 @@ package full
import ( import (
"context" "context"
"fmt"
"strconv" "strconv"
"go.uber.org/fx" "go.uber.org/fx"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "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/v8/evm"
init8 "github.com/filecoin-project/go-state-types/builtin/v8/init"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
@ -27,10 +34,10 @@ type EthModuleAPI interface {
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthInt) (api.EthInt, error) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthInt) (api.EthInt, error)
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthInt, error) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthInt, error)
EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error)
EthGetBlockByNumber(ctx context.Context, blkNum api.EthInt, fullTxInfo bool) (api.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error)
EthGetTransactionByHash(ctx context.Context, txHash api.EthHash) (api.EthTx, error) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error)
EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthInt, error) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthInt, error)
EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (api.EthTxReceipt, error) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error)
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error)
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthInt, txIndex api.EthInt) (api.EthTx, error) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthInt, txIndex api.EthInt) (api.EthTx, error)
EthGetCode(ctx context.Context, address api.EthAddress) (string, error) EthGetCode(ctx context.Context, address api.EthAddress) (string, error)
@ -41,7 +48,7 @@ type EthModuleAPI interface {
NetListening(ctx context.Context) (bool, error) NetListening(ctx context.Context) (bool, error)
EthProtocolVersion(ctx context.Context) (api.EthInt, error) EthProtocolVersion(ctx context.Context) (api.EthInt, error)
EthGasPrice(ctx context.Context) (api.EthBigInt, error) EthGasPrice(ctx context.Context) (api.EthBigInt, error)
EthEstimateGas(ctx context.Context, tx api.EthCall, blkParam string) (api.EthInt, error) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthInt, error)
EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error)
EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error)
EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error)
@ -129,27 +136,38 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash,
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo) return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
} }
func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum api.EthInt, fullTxInfo bool) (api.EthBlock, error) { func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) {
ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(blkNum), nil, false) var num api.EthInt
err := num.UnmarshalJSON([]byte(`"` + blkNum + `"`))
if err != nil {
num = api.EthInt(a.Chain.GetHeaviestTipSet().Height())
}
ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(num), nil, false)
if err != nil { if err != nil {
return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) return api.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err)
} }
return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo) return a.ethBlockFromFilecoinTipSet(ctx, ts, fullTxInfo)
} }
func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash api.EthHash) (api.EthTx, error) { func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.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() cid := txHash.ToCid()
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, cid, api.LookbackNoLimit, true) msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, cid, api.LookbackNoLimit, true)
if err != nil { if err != nil {
return api.EthTx{}, nil return nil, nil
} }
tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup) tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil { if err != nil {
return api.EthTx{}, err return nil, nil
} }
return tx, nil return &tx, nil
} }
func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkParam string) (api.EthInt, error) { func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkParam string) (api.EthInt, error) {
@ -164,29 +182,29 @@ func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAd
return api.EthInt(nonce), nil return api.EthInt(nonce), nil
} }
func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (api.EthTxReceipt, error) { func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) {
cid := txHash.ToCid() cid := txHash.ToCid()
msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, cid, api.LookbackNoLimit, true) msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, cid, api.LookbackNoLimit, true)
if err != nil { if err != nil {
return api.EthTxReceipt{}, err return nil, err
} }
tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup) tx, err := a.ethTxFromFilecoinMessageLookup(ctx, msgLookup)
if err != nil { if err != nil {
return api.EthTxReceipt{}, err return nil, err
} }
replay, err := a.StateAPI.StateReplay(ctx, types.EmptyTSK, cid) replay, err := a.StateAPI.StateReplay(ctx, types.EmptyTSK, cid)
if err != nil { if err != nil {
return api.EthTxReceipt{}, err return nil, err
} }
receipt, err := api.NewEthTxReceipt(tx, msgLookup, replay) receipt, err := api.NewEthTxReceipt(tx, msgLookup, replay)
if err != nil { if err != nil {
return api.EthTxReceipt{}, err return nil, err
} }
return receipt, nil return &receipt, nil
} }
func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error) { func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error) {
@ -267,24 +285,93 @@ func (a *EthModule) EthGasPrice(ctx context.Context) (api.EthBigInt, error) {
} }
func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) { func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) {
return api.EthHash{}, nil txArgs, err := api.ParseEthTxArgs(rawTx)
if err != nil {
return api.EmptyEthHash, err
}
smsg, err := txArgs.ToSignedMessage()
if err != nil {
return api.EmptyEthHash, err
}
cid, err := a.MpoolAPI.MpoolPush(ctx, smsg)
if err != nil {
return api.EmptyEthHash, err
}
return api.EthHashFromCid(cid)
} }
func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.InvocResult, error) { func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.InvocResult, error) {
from, err := tx.From.ToFilecoinAddress() // FIXME: this is a workaround, remove this when f4 address is ready
if err != nil { var from address.Address
return nil, err 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.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")
}
} }
to, err := tx.To.ToFilecoinAddress()
if err != nil { var params []byte
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) var to address.Address
if tx.To == nil {
to = builtintypes.InitActorAddr
constructorParams, err := actors.SerializeParams(&evm.ConstructorParams{
Bytecode: tx.Data,
InputData: []byte{},
})
if err != nil {
return nil, fmt.Errorf("failed to serialize constructor params: %w", err)
}
evmActorCid, ok := actors.GetActorCodeID(actors.Version8, "evm")
if !ok {
return nil, fmt.Errorf("failed to lookup evm actor code CID")
}
params, err = actors.SerializeParams(&init8.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, xerrors.Errorf("cannot get Filecoin address: %w", err)
}
to = addr
params = tx.Data
} }
msg := &types.Message{ msg := &types.Message{
From: from, From: from,
To: to, To: to,
Value: big.Int(tx.Value), Value: big.Int(tx.Value),
Method: abi.MethodNum(2), Method: abi.MethodNum(2),
Params: tx.Data, Params: params,
GasLimit: build.BlockGasLimit, GasLimit: build.BlockGasLimit,
GasFeeCap: big.Zero(), GasFeeCap: big.Zero(),
GasPremium: big.Zero(), GasPremium: big.Zero(),
@ -312,7 +399,7 @@ func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.Invoc
return res, nil return res, nil
} }
func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall, blkParam string) (api.EthInt, error) { func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthInt, error) {
invokeResult, err := a.applyEvmMsg(ctx, tx) invokeResult, err := a.applyEvmMsg(ctx, tx)
if err != nil { if err != nil {
return api.EthInt(0), err return api.EthInt(0), err
@ -388,6 +475,9 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti
} }
func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) { func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup) (api.EthTx, error) {
if msgLookup == nil {
return api.EthTx{}, fmt.Errorf("msg does not exist")
}
cid := msgLookup.Message cid := msgLookup.Message
txHash, err := api.EthHashFromCid(cid) txHash, err := api.EthHashFromCid(cid)
if err != nil { if err != nil {
@ -447,9 +537,9 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku
Gas: api.EthInt(msg.GasLimit), Gas: api.EthInt(msg.GasLimit),
MaxFeePerGas: api.EthBigInt(msg.GasFeeCap), MaxFeePerGas: api.EthBigInt(msg.GasFeeCap),
MaxPriorityFeePerGas: api.EthBigInt(msg.GasPremium), MaxPriorityFeePerGas: api.EthBigInt(msg.GasPremium),
V: api.EthBigIntZero, V: api.EthBytes{},
R: api.EthBigIntZero, R: api.EthBytes{},
S: api.EthBigIntZero, S: api.EthBytes{},
Input: msg.Params, Input: msg.Params,
} }
return tx, nil return tx, nil