From f855dce3244dedb8a81ed077ccb7ac295a7bdd2f Mon Sep 17 00:00:00 2001 From: dustinxie Date: Thu, 19 Sep 2024 14:42:33 -0700 Subject: [PATCH] [action] enable blob tx (#4393) --- action/rlp_tx.go | 3 ++- action/rlp_tx_test.go | 56 +++++++++++++++++++++++++++++++++++++++--- action/tx_blob.go | 14 +++++++++-- action/tx_container.go | 2 +- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/action/rlp_tx.go b/action/rlp_tx.go index 6c88bef589..ab70381032 100644 --- a/action/rlp_tx.go +++ b/action/rlp_tx.go @@ -100,9 +100,10 @@ func ExtractTypeSigPubkey(tx *types.Transaction) (iotextypes.Encoding, []byte, c encoding = iotextypes.Encoding_ETHEREUM_UNPROTECTED signer = types.HomesteadSigner{} } - case types.AccessListTxType, types.DynamicFeeTxType: + case types.AccessListTxType, types.DynamicFeeTxType, types.BlobTxType: // AL txs are defined to use 0 and 1 as their recovery id, // DynamicFee txs are defined to use 0 and 1 as their recovery id, + // Blob txs are defined to use 0 and 1 as their recovery id, // add 27 to become equivalent to unprotected Homestead signatures. V = new(big.Int).Add(V, big.NewInt(27)) default: diff --git a/action/rlp_tx_test.go b/action/rlp_tx_test.go index 7ad16166e7..42659482d4 100644 --- a/action/rlp_tx_test.go +++ b/action/rlp_tx_test.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" @@ -304,14 +305,23 @@ var ( nil, "46e367af6c609032b85e7d3f40f0af3fcb59779b55d92eefea2ee1dbdaca41fa", }, + { + "blobtx", 120, 21000, "1000000000", "0", + "0x3141df3f2e4415533bb6d6be2A351B2db9ee84EF", + _evmNetworkID, + iotextypes.Encoding_ETHEREUM_EIP155, + []byte{1, 2, 3}, + "526b46d97b334cc5edb6095448406c9df74c8d6310d22044cb9a3a2a305bc398", + }, } ) func TestEthTxDecodeVerify(t *testing.T) { require := require.New(t) var ( - sk = MustNoErrorV(crypto.HexStringToPrivateKey("a000000000000000000000000000000000000000000000000000000000000000")) - pkhash = sk.PublicKey().Address().Hex() + sk = MustNoErrorV(crypto.HexStringToPrivateKey("a000000000000000000000000000000000000000000000000000000000000000")) + pkhash = sk.PublicKey().Address().Hex() + testBlob = createTestBlobTxData() ) checkSelp := func(selp *SealedEnvelope, tx *types.Transaction, e rlpTest) { @@ -459,11 +469,22 @@ func TestEthTxDecodeVerify(t *testing.T) { case types.LegacyTxType: require.Equal(v.price, evmTx.GasPrice().String()) require.Nil(tx.AccessList()) + case types.BlobTxType: + require.Equal(testBlob.blobFeeCap.ToBig(), tx.BlobGasFeeCap()) + require.Equal(testBlob.hashes(), tx.BlobHashes()) + require.Equal(testBlob.sidecar, tx.BlobTxSidecar()) + require.Equal(selp.BlobGasFeeCap(), tx.BlobGasFeeCap()) + require.Equal(selp.BlobHashes(), tx.BlobHashes()) + require.Equal(selp.BlobTxSidecar(), tx.BlobTxSidecar()) + fallthrough case types.DynamicFeeTxType: require.Equal(v.price, evmTx.GasTipCap().String()) tip := MustBeTrueV(new(big.Int).SetString(v.price, 10)) require.Equal(tip.Lsh(tip, 1), tx.GasFeeCap()) require.Equal(tx.GasPrice(), tx.GasFeeCap()) + require.Equal(selp.GasTipCap(), evmTx.GasTipCap()) + require.Equal(selp.GasFeeCap(), evmTx.GasFeeCap()) + require.Equal(selp.GasPrice(), evmTx.GasPrice()) fallthrough case types.AccessListTxType: require.Equal(3, len(tx.AccessList())) @@ -854,7 +875,7 @@ func convertToNativeProto(tx *types.Transaction, actType string) (*iotextypes.Ac err error ) switch actType { - case "transfer": + case "transfer", "blobtx": elp, err = elpBuilder.BuildTransfer(tx) case "execution", "unprotected", "accesslist", "dynamicfee": elp, err = elpBuilder.BuildExecution(tx) @@ -894,7 +915,7 @@ func checkContract(to string, actType string) func(context.Context, *common.Addr } } switch actType { - case "transfer": + case "transfer", "blobtx": return func(context.Context, *common.Address) (bool, bool, bool, error) { return false, false, false, nil } @@ -1014,6 +1035,33 @@ func generateRLPTestRaw(sk *ecdsa.PrivateKey, test *rlpTest) string { {Address: _c2, StorageKeys: []common.Hash{_k2, _k3, _k4, _k1}}, }, } + case "blobtx": + price := new(uint256.Int) + if err := price.SetFromDecimal(test.price); err != nil { + panic(err.Error()) + } + value := new(uint256.Int) + if err := value.SetFromDecimal(test.amount); err != nil { + panic(err.Error()) + } + blob := createTestBlobTxData() + tx = &types.BlobTx{ + Nonce: test.nonce, + GasTipCap: price, + GasFeeCap: new(uint256.Int).Lsh(price, 1), + Gas: test.limit, + To: *to, + Value: value, + Data: test.data, + AccessList: types.AccessList{ + {Address: common.Address{}, StorageKeys: nil}, + {Address: _c1, StorageKeys: []common.Hash{_k1, {}, _k3}}, + {Address: _c2, StorageKeys: []common.Hash{_k2, _k3, _k4, _k1}}, + }, + BlobFeeCap: blob.gasFeeCap(), + BlobHashes: blob.hashes(), + Sidecar: blob.sidecar, + } default: panic("not supported") } diff --git a/action/tx_blob.go b/action/tx_blob.go index cf5f63dc55..15cac553c0 100644 --- a/action/tx_blob.go +++ b/action/tx_blob.go @@ -167,6 +167,16 @@ func (tx *BlobTx) setChainID(n uint32) { } func (tx *BlobTx) toEthTx(to *common.Address, value *big.Int, data []byte) *types.Transaction { - // TODO: enable blob tx - return nil + return types.NewTx(&types.BlobTx{ + Nonce: tx.nonce, + GasTipCap: tx.tipCap(), + GasFeeCap: tx.feeCap(), + Gas: tx.gasLimit, + To: *to, + Value: uint256.MustFromBig(value), + Data: data, + AccessList: tx.accessList, + BlobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()), + BlobHashes: tx.BlobHashes(), + }) } diff --git a/action/tx_container.go b/action/tx_container.go index 3d3e5a0107..2d470a0ffb 100644 --- a/action/tx_container.go +++ b/action/tx_container.go @@ -37,7 +37,7 @@ func (etx *txContainer) typeToEncoding() (iotextypes.Encoding, error) { // tx has pre-EIP155 signature return iotextypes.Encoding_ETHEREUM_UNPROTECTED, nil } - case types.AccessListTxType, types.DynamicFeeTxType: + case types.AccessListTxType, types.DynamicFeeTxType, types.BlobTxType: default: return 0, ErrNotSupported }