Skip to content

Commit c9c0707

Browse files
feat: ETH compatibility in Filecoin : Support Homestead and EIP-155 Ethereum 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 <[email protected]> * 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 <[email protected]>
1 parent 423d8a7 commit c9c0707

29 files changed

+2685
-741
lines changed

build/openrpc/full.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6543,6 +6543,7 @@
65436543
"gas": "0x5",
65446544
"maxFeePerGas": "0x0",
65456545
"maxPriorityFeePerGas": "0x0",
6546+
"gasPrice": "0x0",
65466547
"accessList": [
65476548
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
65486549
],
@@ -6598,6 +6599,10 @@
65986599
"title": "number",
65996600
"type": "number"
66006601
},
6602+
"gasPrice": {
6603+
"additionalProperties": false,
6604+
"type": "object"
6605+
},
66016606
"hash": {
66026607
"items": {
66036608
"description": "Number is a number",
@@ -6738,6 +6743,7 @@
67386743
"gas": "0x5",
67396744
"maxFeePerGas": "0x0",
67406745
"maxPriorityFeePerGas": "0x0",
6746+
"gasPrice": "0x0",
67416747
"accessList": [
67426748
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
67436749
],
@@ -6793,6 +6799,10 @@
67936799
"title": "number",
67946800
"type": "number"
67956801
},
6802+
"gasPrice": {
6803+
"additionalProperties": false,
6804+
"type": "object"
6805+
},
67966806
"hash": {
67976807
"items": {
67986808
"description": "Number is a number",
@@ -6925,6 +6935,7 @@
69256935
"gas": "0x5",
69266936
"maxFeePerGas": "0x0",
69276937
"maxPriorityFeePerGas": "0x0",
6938+
"gasPrice": "0x0",
69286939
"accessList": [
69296940
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
69306941
],
@@ -6980,6 +6991,10 @@
69806991
"title": "number",
69816992
"type": "number"
69826993
},
6994+
"gasPrice": {
6995+
"additionalProperties": false,
6996+
"type": "object"
6997+
},
69836998
"hash": {
69846999
"items": {
69857000
"description": "Number is a number",
@@ -7129,6 +7144,7 @@
71297144
"gas": "0x5",
71307145
"maxFeePerGas": "0x0",
71317146
"maxPriorityFeePerGas": "0x0",
7147+
"gasPrice": "0x0",
71327148
"accessList": [
71337149
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
71347150
],
@@ -7184,6 +7200,10 @@
71847200
"title": "number",
71857201
"type": "number"
71867202
},
7203+
"gasPrice": {
7204+
"additionalProperties": false,
7205+
"type": "object"
7206+
},
71877207
"hash": {
71887208
"items": {
71897209
"description": "Number is a number",

build/openrpc/gateway.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3132,6 +3132,7 @@
31323132
"gas": "0x5",
31333133
"maxFeePerGas": "0x0",
31343134
"maxPriorityFeePerGas": "0x0",
3135+
"gasPrice": "0x0",
31353136
"accessList": [
31363137
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
31373138
],
@@ -3187,6 +3188,10 @@
31873188
"title": "number",
31883189
"type": "number"
31893190
},
3191+
"gasPrice": {
3192+
"additionalProperties": false,
3193+
"type": "object"
3194+
},
31903195
"hash": {
31913196
"items": {
31923197
"description": "Number is a number",
@@ -3336,6 +3341,7 @@
33363341
"gas": "0x5",
33373342
"maxFeePerGas": "0x0",
33383343
"maxPriorityFeePerGas": "0x0",
3344+
"gasPrice": "0x0",
33393345
"accessList": [
33403346
"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"
33413347
],
@@ -3391,6 +3397,10 @@
33913397
"title": "number",
33923398
"type": "number"
33933399
},
3400+
"gasPrice": {
3401+
"additionalProperties": false,
3402+
"type": "object"
3403+
},
33943404
"hash": {
33953405
"items": {
33963406
"description": "Number is a number",

chain/consensus/common.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/filecoin-project/lotus/chain/stmgr"
3030
"github.com/filecoin-project/lotus/chain/store"
3131
"github.com/filecoin-project/lotus/chain/types"
32+
"github.com/filecoin-project/lotus/chain/types/ethtypes"
3233
"github.com/filecoin-project/lotus/chain/vm"
3334
"github.com/filecoin-project/lotus/lib/async"
3435
"github.com/filecoin-project/lotus/metrics"
@@ -131,6 +132,18 @@ func CommonBlkChecks(ctx context.Context, sm *stmgr.StateManager, cs *store.Chai
131132
}
132133
}
133134

135+
func IsValidEthTxForSending(nv network.Version, smsg *types.SignedMessage) bool {
136+
ethTx, err := ethtypes.EthTransactionFromSignedFilecoinMessage(smsg)
137+
if err != nil {
138+
return false
139+
}
140+
141+
if nv < network.Version23 && ethTx.Type() != ethtypes.EIP1559TxType {
142+
return false
143+
}
144+
return true
145+
}
146+
134147
func IsValidForSending(nv network.Version, act *types.Actor) bool {
135148
// Before nv18 (Hygge), we only supported built-in account actors as senders.
136149
//
@@ -276,6 +289,10 @@ func checkBlockMessages(ctx context.Context, sm *stmgr.StateManager, cs *store.C
276289
return xerrors.Errorf("block had invalid signed message at index %d: %w", i, err)
277290
}
278291

292+
if m.Signature.Type == crypto.SigTypeDelegated && !IsValidEthTxForSending(nv, m) {
293+
return xerrors.Errorf("network version should be atleast NV23 for sending legacy ETH transactions; but current network version is %d", nv)
294+
}
295+
279296
if err := checkMsg(m); err != nil {
280297
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
281298
}

chain/consensus/signatures.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,42 @@ import (
1818
// must be recognized by the registered verifier for the signature type.
1919
func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error {
2020
var digest []byte
21+
signatureType := msg.Signature.Type
22+
signatureCopy := msg.Signature
2123

22-
typ := msg.Signature.Type
23-
switch typ {
24+
switch signatureType {
2425
case crypto.SigTypeDelegated:
25-
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message)
26+
signatureCopy.Data = make([]byte, len(msg.Signature.Data))
27+
copy(signatureCopy.Data, msg.Signature.Data)
28+
ethTx, err := ethtypes.EthTransactionFromSignedFilecoinMessage(msg)
2629
if err != nil {
27-
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
30+
return xerrors.Errorf("failed to reconstruct Ethereum transaction: %w", err)
2831
}
29-
roundTripMsg, err := txArgs.ToUnsignedMessage(msg.Message.From)
32+
33+
filecoinMsg, err := ethTx.ToUnsignedFilecoinMessage(msg.Message.From)
3034
if err != nil {
31-
return xerrors.Errorf("failed to reconstruct filecoin msg: %w", err)
35+
return xerrors.Errorf("failed to reconstruct Filecoin message: %w", err)
3236
}
3337

34-
if !msg.Message.Equals(roundTripMsg) {
35-
return xerrors.New("ethereum tx failed to roundtrip")
38+
if !msg.Message.Equals(filecoinMsg) {
39+
return xerrors.New("Ethereum transaction roundtrip mismatch")
3640
}
3741

38-
rlpEncodedMsg, err := txArgs.ToRlpUnsignedMsg()
42+
rlpEncodedMsg, err := ethTx.ToRlpUnsignedMsg()
3943
if err != nil {
40-
return xerrors.Errorf("failed to repack eth rlp message: %w", err)
44+
return xerrors.Errorf("failed to encode RLP message: %w", err)
4145
}
4246
digest = rlpEncodedMsg
47+
signatureCopy.Data, err = ethTx.ToVerifiableSignature(signatureCopy.Data)
48+
if err != nil {
49+
return xerrors.Errorf("failed to verify signature: %w", err)
50+
}
4351
default:
4452
digest = msg.Message.Cid().Bytes()
4553
}
4654

47-
if err := sigs.Verify(&msg.Signature, signer, digest); err != nil {
48-
return xerrors.Errorf("message %s has invalid signature (type %d): %w", msg.Cid(), typ, err)
55+
if err := sigs.Verify(&signatureCopy, signer, digest); err != nil {
56+
return xerrors.Errorf("invalid signature for message %s (type %d): %w", msg.Cid(), signatureType, err)
4957
}
5058
return nil
5159
}

chain/messagepool/messagepool.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,11 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs
887887
nv := mp.api.StateNetworkVersion(ctx, epoch)
888888

889889
// TODO: I'm not thrilled about depending on filcns here, but I prefer this to duplicating logic
890+
891+
if m.Signature.Type == crypto.SigTypeDelegated && !consensus.IsValidEthTxForSending(nv, m) {
892+
return false, xerrors.Errorf("network version should be atleast NV23 for sending legacy ETH transactions; but current network version is %d", nv)
893+
}
894+
890895
if !consensus.IsValidForSending(nv, senderAct) {
891896
return false, xerrors.Errorf("sender actor %s is not a valid top-level sender", m.Message.From)
892897
}

chain/messagesigner/messagesigner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key {
196196

197197
func SigningBytes(msg *types.Message, sigType address.Protocol) ([]byte, error) {
198198
if sigType == address.Delegated {
199-
txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg)
199+
txArgs, err := ethtypes.Eth1559TxArgsFromUnsignedFilecoinMessage(msg)
200200
if err != nil {
201201
return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
202202
}

0 commit comments

Comments
 (0)