Skip to content

Commit

Permalink
feat: ETH compatibility in Filecoin : Support Homestead and EIP-155 E…
Browse files Browse the repository at this point in the history
…thereum transactions("legacy" transactions) in Filecoin (#11969)

* poc for eth legacy tx

* print statements

* finished

* tests work

* remove print statements

* Remove all print statements

* remove extraneous changes

* cleaned up code and interface

* run make jen

* dont duplicate signature

* go mod tidy and remove prints

* clean up tests

* test for conversion

* changes as per review

* more unit tests for legacy txns

* Apply suggestions from code review

Co-authored-by: Rod Vagg <rod@vagg.org>

* address review comments from Rodd

* changes as per zen's 2nd review

* go mod tidy

* feat: ETH compatibility in Filecoin : Support EIP-155 Ethereum transactions in Filecoin (#11970)

* itests passing for 155 tx

* first working version for EIP-155 transactions

* green itest

* add docs

* tests

* remove print stmt

* remove print stmt

* validate signature

* changes as per zen's review

* correct signature verification

* gate tx by Network Version

* handle arajsek review

* fix imports order

* fix lint

* dont lock in mpool for network gating ETH messages

* sender can be an ID address

---------

Co-authored-by: Rod Vagg <rod@vagg.org>
  • Loading branch information
aarshkshah1992 and rvagg committed Jun 5, 2024
1 parent 423d8a7 commit c9c0707
Show file tree
Hide file tree
Showing 29 changed files with 2,685 additions and 741 deletions.
20 changes: 20 additions & 0 deletions build/openrpc/full.json
Original file line number Diff line number Diff line change
Expand Up @@ -6543,6 +6543,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -6598,6 +6599,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down Expand Up @@ -6738,6 +6743,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -6793,6 +6799,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down Expand Up @@ -6925,6 +6935,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -6980,6 +6991,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down Expand Up @@ -7129,6 +7144,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -7184,6 +7200,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down
10 changes: 10 additions & 0 deletions build/openrpc/gateway.json
Original file line number Diff line number Diff line change
Expand Up @@ -3132,6 +3132,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -3187,6 +3188,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down Expand Up @@ -3336,6 +3341,7 @@
"gas": "0x5",
"maxFeePerGas": "0x0",
"maxPriorityFeePerGas": "0x0",
"gasPrice": "0x0",
"accessList": [
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
],
Expand Down Expand Up @@ -3391,6 +3397,10 @@
"title": "number",
"type": "number"
},
"gasPrice": {
"additionalProperties": false,
"type": "object"
},
"hash": {
"items": {
"description": "Number is a number",
Expand Down
17 changes: 17 additions & 0 deletions chain/consensus/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/lib/async"
"github.com/filecoin-project/lotus/metrics"
Expand Down Expand Up @@ -131,6 +132,18 @@ func CommonBlkChecks(ctx context.Context, sm *stmgr.StateManager, cs *store.Chai
}
}

func IsValidEthTxForSending(nv network.Version, smsg *types.SignedMessage) bool {
ethTx, err := ethtypes.EthTransactionFromSignedFilecoinMessage(smsg)
if err != nil {
return false
}

if nv < network.Version23 && ethTx.Type() != ethtypes.EIP1559TxType {
return false
}
return true
}

func IsValidForSending(nv network.Version, act *types.Actor) bool {
// Before nv18 (Hygge), we only supported built-in account actors as senders.
//
Expand Down Expand Up @@ -276,6 +289,10 @@ func checkBlockMessages(ctx context.Context, sm *stmgr.StateManager, cs *store.C
return xerrors.Errorf("block had invalid signed message at index %d: %w", i, err)
}

if m.Signature.Type == crypto.SigTypeDelegated && !IsValidEthTxForSending(nv, m) {
return xerrors.Errorf("network version should be atleast NV23 for sending legacy ETH transactions; but current network version is %d", nv)
}

if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
}
Expand Down
32 changes: 20 additions & 12 deletions chain/consensus/signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,42 @@ import (
// must be recognized by the registered verifier for the signature type.
func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error {
var digest []byte
signatureType := msg.Signature.Type
signatureCopy := msg.Signature

typ := msg.Signature.Type
switch typ {
switch signatureType {
case crypto.SigTypeDelegated:
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message)
signatureCopy.Data = make([]byte, len(msg.Signature.Data))
copy(signatureCopy.Data, msg.Signature.Data)
ethTx, err := ethtypes.EthTransactionFromSignedFilecoinMessage(msg)
if err != nil {
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
return xerrors.Errorf("failed to reconstruct Ethereum transaction: %w", err)
}
roundTripMsg, err := txArgs.ToUnsignedMessage(msg.Message.From)

filecoinMsg, err := ethTx.ToUnsignedFilecoinMessage(msg.Message.From)
if err != nil {
return xerrors.Errorf("failed to reconstruct filecoin msg: %w", err)
return xerrors.Errorf("failed to reconstruct Filecoin message: %w", err)
}

if !msg.Message.Equals(roundTripMsg) {
return xerrors.New("ethereum tx failed to roundtrip")
if !msg.Message.Equals(filecoinMsg) {
return xerrors.New("Ethereum transaction roundtrip mismatch")
}

rlpEncodedMsg, err := txArgs.ToRlpUnsignedMsg()
rlpEncodedMsg, err := ethTx.ToRlpUnsignedMsg()
if err != nil {
return xerrors.Errorf("failed to repack eth rlp message: %w", err)
return xerrors.Errorf("failed to encode RLP message: %w", err)
}
digest = rlpEncodedMsg
signatureCopy.Data, err = ethTx.ToVerifiableSignature(signatureCopy.Data)
if err != nil {
return xerrors.Errorf("failed to verify signature: %w", err)
}
default:
digest = msg.Message.Cid().Bytes()
}

if err := sigs.Verify(&msg.Signature, signer, digest); err != nil {
return xerrors.Errorf("message %s has invalid signature (type %d): %w", msg.Cid(), typ, err)
if err := sigs.Verify(&signatureCopy, signer, digest); err != nil {
return xerrors.Errorf("invalid signature for message %s (type %d): %w", msg.Cid(), signatureType, err)
}
return nil
}
Expand Down
5 changes: 5 additions & 0 deletions chain/messagepool/messagepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,11 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs
nv := mp.api.StateNetworkVersion(ctx, epoch)

// TODO: I'm not thrilled about depending on filcns here, but I prefer this to duplicating logic

if m.Signature.Type == crypto.SigTypeDelegated && !consensus.IsValidEthTxForSending(nv, m) {
return false, xerrors.Errorf("network version should be atleast NV23 for sending legacy ETH transactions; but current network version is %d", nv)
}

if !consensus.IsValidForSending(nv, senderAct) {
return false, xerrors.Errorf("sender actor %s is not a valid top-level sender", m.Message.From)
}
Expand Down
2 changes: 1 addition & 1 deletion chain/messagesigner/messagesigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {

func SigningBytes(msg *types.Message, sigType address.Protocol) ([]byte, error) {
if sigType == address.Delegated {
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg)
txArgs, err := ethtypes.Eth1559TxArgsFromUnsignedFilecoinMessage(msg)
if err != nil {
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
}
Expand Down
Loading

0 comments on commit c9c0707

Please sign in to comment.