github.com/iotexproject/iotex-core@v1.14.1-rc1/action/rlp_tx_test.go (about) 1 package action 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "math/big" 7 "testing" 8 9 "github.com/ethereum/go-ethereum/common" 10 "github.com/ethereum/go-ethereum/core/types" 11 "github.com/iotexproject/go-pkgs/crypto" 12 "github.com/iotexproject/go-pkgs/hash" 13 "github.com/iotexproject/iotex-address/address" 14 "github.com/iotexproject/iotex-proto/golang/iotextypes" 15 "github.com/stretchr/testify/require" 16 "google.golang.org/protobuf/proto" 17 ) 18 19 func TestGenerateRlp(t *testing.T) { 20 require := require.New(t) 21 22 ab := AbstractAction{ 23 version: 1, 24 nonce: 2, 25 gasLimit: 1000, 26 gasPrice: new(big.Int), 27 } 28 rlpTsf := &Transfer{ 29 AbstractAction: ab, 30 recipient: "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3071", 31 } 32 rlpTsf1 := &Transfer{ 33 AbstractAction: ab, 34 amount: big.NewInt(100), 35 recipient: "", 36 } 37 hT1, _ := hex.DecodeString("87e39e819193ae46472eb1320739b34c4c3b38ea321c7cc503432bdcfd0cbf15") 38 rlpTsf2 := &Transfer{ 39 AbstractAction: ab, 40 recipient: "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3070", 41 } 42 hT2, _ := hex.DecodeString("eaaf38a552809a9bdb1509c8093bd2c74eb07baff862dae692c1d2b865478b14") 43 rlpExec := &Execution{ 44 AbstractAction: ab, 45 amount: big.NewInt(100), 46 data: _signByte, 47 } 48 hE1, _ := hex.DecodeString("fcdd0c3d07f438d6e67ea852b40e5dc256d75f5e1fa9ac3ca96030efeb634150") 49 rlpExec1 := &Execution{ 50 AbstractAction: ab, 51 contract: "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3070", 52 amount: big.NewInt(100), 53 data: _signByte, 54 } 55 hE2, _ := hex.DecodeString("fee3db88ee7d7defa9eded672d08fc8641f760f3a11d404a53276ad6f412b8a5") 56 rlpTests := []struct { 57 act Action 58 sig []byte 59 err string 60 hash hash.Hash256 61 }{ 62 {nil, _validSig, ErrNilAction.Error(), hash.ZeroHash256}, 63 {rlpTsf, _validSig, address.ErrInvalidAddr.Error(), hash.ZeroHash256}, 64 {rlpTsf1, _signByte, "address length = 0, expecting 41", hash.ZeroHash256}, 65 {rlpTsf1, _validSig, "", hash.BytesToHash256(hT1)}, 66 {rlpTsf2, _validSig, "", hash.BytesToHash256(hT2)}, 67 {rlpExec, _validSig, "", hash.BytesToHash256(hE1)}, 68 {rlpExec1, _validSig, "", hash.BytesToHash256(hE2)}, 69 } 70 71 for _, v := range rlpTests { 72 act, ok := v.act.(EthCompatibleAction) 73 if !ok { 74 require.Contains(v.err, ErrNilAction.Error()) 75 continue 76 } 77 tx, err := act.ToEthTx(0) 78 if err != nil { 79 require.Contains(err.Error(), v.err) 80 continue 81 } 82 signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, _evmNetworkID) 83 require.NoError(err) 84 h, err := rlpSignedHash(tx, signer, v.sig) 85 if err != nil { 86 require.Contains(err.Error(), v.err) 87 } 88 require.Equal(v.hash, h) 89 } 90 } 91 92 func TestRlpDecodeVerify(t *testing.T) { 93 require := require.New(t) 94 95 oldTests := rlpTests[:len(rlpTests)-1] 96 for _, v := range oldTests { 97 // decode received RLP tx 98 tx, sig, pubkey, err := DecodeRawTx(v.raw, _evmNetworkID) 99 require.NoError(err) 100 require.EqualValues(types.LegacyTxType, tx.Type()) 101 require.True(tx.Protected()) 102 require.EqualValues(v.chainID, tx.ChainId().Uint64()) 103 require.Equal(v.pubkey, pubkey.HexString()) 104 require.Equal(v.pkhash, hex.EncodeToString(pubkey.Hash())) 105 106 // convert to our Execution 107 pb := &iotextypes.Action{ 108 Encoding: iotextypes.Encoding_ETHEREUM_EIP155, 109 } 110 pb.Core = convertToNativeProto(tx, v.actType) 111 pb.SenderPubKey = pubkey.Bytes() 112 pb.Signature = sig 113 114 // send on wire 115 bs, err := proto.Marshal(pb) 116 require.NoError(err) 117 118 // receive from API 119 proto.Unmarshal(bs, pb) 120 selp := &SealedEnvelope{} 121 require.NoError(selp.loadProto(pb, _evmNetworkID)) 122 act, ok := selp.Action().(EthCompatibleAction) 123 require.True(ok) 124 rlpTx, err := act.ToEthTx(_evmNetworkID) 125 require.NoError(err) 126 127 // verify against original tx 128 require.Equal(v.nonce, rlpTx.Nonce()) 129 require.Equal(v.price, rlpTx.GasPrice().String()) 130 require.Equal(v.limit, rlpTx.Gas()) 131 if v.to == "" { 132 require.Nil(rlpTx.To()) 133 } else { 134 require.Equal(v.to, rlpTx.To().Hex()) 135 } 136 require.Equal(v.amount, rlpTx.Value().String()) 137 require.Equal(v.dataLen, len(rlpTx.Data())) 138 h, err := selp.Hash() 139 require.NoError(err) 140 require.Equal(v.hash, hex.EncodeToString(h[:])) 141 require.Equal(pubkey, selp.SrcPubkey()) 142 require.True(bytes.Equal(sig, selp.signature)) 143 raw, err := selp.envelopeHash() 144 require.NoError(err) 145 signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, _evmNetworkID) 146 require.NoError(err) 147 rawHash := signer.Hash(tx) 148 require.True(bytes.Equal(rawHash[:], raw[:])) 149 require.NotEqual(raw, h) 150 require.NoError(selp.VerifySignature()) 151 } 152 } 153 154 var ( 155 // deterministic deployment: https://github.com/Arachnid/deterministic-deployment-proxy 156 // see example at https://etherscan.io/tx/0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26 157 deterministicDeploymentTx = "0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222" 158 159 // example access list tx, created with a random chainID value = 0x7a69 = 31337 160 accessListTx = "0x01f8a0827a690184ee6b280082520894a0ee7a142d267c1f36714e4a8f75612f20a797206480f838f794a0ee7a142d267c1f36714e4a8f75612f20a79720e1a0000000000000000000000000000000000000000000000000000000000000000001a0eb211dfd353d76d43ea31a130ff36ac4eb7b379eae4d49fa2376741daf32f9ffa07ab673241d75e103f81ddd4aa34dd6849faf2f0f593eebe61a68fed74490a348" 161 162 rlpTests = []struct { 163 actType string 164 raw string 165 nonce uint64 166 limit uint64 167 price string 168 amount string 169 to string 170 chainID uint32 171 encoding iotextypes.Encoding 172 dataLen int 173 hash string 174 pubkey string 175 pkhash string 176 }{ 177 { 178 "transfer", 179 "f86e8085e8d4a51000825208943141df3f2e4415533bb6d6be2a351b2db9ee84ef88016345785d8a0000808224c6a0204d25fc0d7d8b3fdf162c6ee820f888f5533b1c382d79d5cbc8ec1d9091a9a8a016f1a58d7e0d0fd24be800f64a2d6433c5fcb31e3fc7562b7fbe62bc382a95bb", 180 0, 181 21000, 182 "1000000000000", 183 "100000000000000000", 184 "0x3141df3f2e4415533bb6d6be2A351B2db9ee84EF", 185 _evmNetworkID, 186 iotextypes.Encoding_ETHEREUM_EIP155, 187 0, 188 "eead45fe6b510db9ed6dce9187280791c04bbaadd90c54a7f4b1f75ced382ff1", 189 "041ba784140be115e8fa8698933e9318558a895c75c7943100f0677e4d84ff2763ff68720a0d22c12d093a2d692d1e8292c3b7672fccf3b3db46a6e0bdad93be17", 190 "87eea07540789af85b64947aea21a3f00400b597", 191 }, 192 { 193 "execution", 194 "f8ab0d85e8d4a5100082520894ac7ac39de679b19aae042c0ce19facb86e0a411780b844a9059cbb0000000000000000000000003141df3f2e4415533bb6d6be2a351b2db9ee84ef000000000000000000000000000000000000000000000000000000003b9aca008224c5a0fac4e25db03c99fec618b74a962d322a334234696eb62c7e5b9889132ff4f4d7a02c88e451572ca36b6f690ce23ff9d6695dd71e888521fa706a8fc8c279099a61", 195 13, 196 21000, 197 "1000000000000", 198 "0", 199 "0xAC7AC39De679b19AaE042c0cE19fAcB86e0A4117", 200 _evmNetworkID, 201 iotextypes.Encoding_ETHEREUM_EIP155, 202 68, 203 "7467dd6ccd4f3d7b6dc0002b26a45ad0b75a1793da4e3557cf6ff2582cbe25c9", 204 "041ba784140be115e8fa8698933e9318558a895c75c7943100f0677e4d84ff2763ff68720a0d22c12d093a2d692d1e8292c3b7672fccf3b3db46a6e0bdad93be17", 205 "87eea07540789af85b64947aea21a3f00400b597", 206 }, 207 { 208 "execution", 209 "f9024f2e830f42408381b3208080b901fc608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a72315820e54fe55a78b9d8bec22b4d3e6b94b7e59799daee3940423eb1aa30fe643eeb9a64736f6c634300051000328224c5a0439310c2d5509fc42486171b910cf8107542c86e23202a3a8ba43129cabcdbfea038966d36b41916f619c64bdc8c3ddcb021b35ea95d44875eb8201e9422fd98f0", 210 46, 211 8500000, 212 "1000000", 213 "0", 214 EmptyAddress, 215 _evmNetworkID, 216 iotextypes.Encoding_ETHEREUM_EIP155, 217 508, 218 "b676128dae841742e3ab6e518acb30badc6b26230fe870821d1de08c85823067", 219 "049c6567f527f8fc98c0875d3d80097fcb4d5b7bfe037fc9dd5dbeaf563d58d7ff17a4f2b85df9734ecdb276622738e28f0b7cf224909ab7b128c5ca748729b0d2", 220 "1904bfcb93edc9bf961eead2e5c0de81dcc1d37d", 221 }, 222 { 223 "stakeCreate", 224 "f901670980828ca09404c22afae6a03438b8fed74cb1cf441168df3f1280b90104a3d374c400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c6a02d359322fb1eb0ef44008b587d28160fb237ae716da2735aef9ce2702af52151a03518f334c585c31cec1d9c0ec81fd4c4f70d3ab661502a5aeb1f6eb07bc01854", 225 9, 226 36000, 227 "0", 228 "0", 229 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 230 _evmNetworkID, 231 iotextypes.Encoding_ETHEREUM_EIP155, 232 260, 233 "f59e5f9ba10ec50fdd1ebb41c75c6d54cfc634428620930b6ba6300847127241", 234 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 235 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 236 }, 237 { 238 "stakeAddDeposit", 239 "f8e60980825aa09404c22afae6a03438b8fed74cb1cf441168df3f1280b88434e8e14500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000008224c6a0b4af40981b992eab4f15afe1bab1d4c498069cae8fa4ea3e0800d732f282fadea073de47b280905d5ccd4fc329e9c1f10b0bdefe1f4a3f4f8b00918680428ae7dd", 240 9, 241 23200, 242 "0", 243 "0", 244 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 245 _evmNetworkID, 246 iotextypes.Encoding_ETHEREUM_EIP155, 247 132, 248 "8823b599b46cd907c4691aa71b5668b835be76a8358fa9beb866610e27598592", 249 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 250 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 251 }, 252 { 253 "changeCandidate", 254 "f9012609808273a09404c22afae6a03438b8fed74cb1cf441168df3f1280b8c4fb3d51380000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c6a06087932dec4df781917c12d31feb80c8e61b2317e3a0820401f3c095746a765da0549df65b7d94fdec196bc70e6dda056fec873664c064036e55fd3bc7e766a595", 255 9, 256 29600, 257 "0", 258 "0", 259 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 260 _evmNetworkID, 261 iotextypes.Encoding_ETHEREUM_EIP155, 262 196, 263 "23f29aebf4b193b02dd78866d56ea7a7b1cdbf27604d34868bb82993c216b4ec", 264 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 265 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 266 }, 267 { 268 "unstake", 269 "f8c609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8642bde151d0000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a0bd261cf9c6a2412272c660742a902965611d838176b2ad22b39219dadeedb312a02beef231cc90e4fbd6b928b28aea6ca1ccaf4f793f9d05bc0186e0e09b920a0a", 270 9, 271 21000, 272 "0", 273 "0", 274 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 275 _evmNetworkID, 276 iotextypes.Encoding_ETHEREUM_EIP155, 277 100, 278 "0c8560b135d325573e6aad484d71e2887835acce7fd4a78eddcb24efe6071516", 279 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 280 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 281 }, 282 { 283 "withdrawStake", 284 "f8c609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b864d179ffb50000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c5a0526ec8247ce5ae1c8542776cf28a85c7bc2f17e1abc3de5cfbfd20fd85aeeca3a07a6db0a7ae08b6b6aeeae4a1446dcc6f090589e7835d63ebc0a1db783c5e2c89", 285 9, 286 21000, 287 "0", 288 "0", 289 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 290 _evmNetworkID, 291 iotextypes.Encoding_ETHEREUM_EIP155, 292 100, 293 "49cc2e14f3d1c03d7e36686d962995ea0f30f65f948d5a59181a5504bc58c102", 294 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 295 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 296 }, 297 { 298 "restake", 299 "f9010609808267209404c22afae6a03438b8fed74cb1cf441168df3f1280b8a44c4fee4b000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000008224c5a0078638f1f00ab532522558e2e4f394f13bfe134a8687ac4639ebead60f63e0dba019dc91f08c1f422de44aa7e6b25ada0632f29bc22242900b3a60f7f371301f02", 300 9, 301 26400, 302 "0", 303 "0", 304 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 305 _evmNetworkID, 306 iotextypes.Encoding_ETHEREUM_EIP155, 307 164, 308 "c3d30b0fccf9d59ece79419d329e50082a8b6d86dee1b9f424f8852e154713d1", 309 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 310 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 311 }, 312 { 313 "transferStake", 314 "f8e60980825aa09404c22afae6a03438b8fed74cb1cf441168df3f1280b8849cb560bb0000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000008224c5a07fd84321b04de059cbfdf12dcd383d3e554c569705f32035bc435b8d996c8bdba00df629ef4d9135d73bb60d49815761bc0a6ee7eb66770106dc9e809cd105d570", 315 9, 316 23200, 317 "0", 318 "0", 319 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 320 _evmNetworkID, 321 iotextypes.Encoding_ETHEREUM_EIP155, 322 132, 323 "a60b2546839e889a0ef89be4f224fb70dab3e4ddb6f65391ff708b01116593c1", 324 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 325 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 326 }, 327 { 328 "candidateRegister", 329 "f901c709808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b90164bee5f7b700000000000000000000000000000000000000000000000000000000000001000000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d82400000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c5a07b4fd9921e47c13bb52fc5e0df47f4dc0bffcf6e7877e13c7e559b4a7d3b9825a0073a3a029822aa43506834bef8b1ed30d6bb436d758d7cf583deb48a4efefd6a", 330 9, 331 21000, 332 "0", 333 "0", 334 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 335 _evmNetworkID, 336 iotextypes.Encoding_ETHEREUM_EIP155, 337 356, 338 "9aa470cbdc3b3fd8f51aae4770d6a58cf4016be18201f0efbae6d83d0b2aa096", 339 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 340 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 341 }, 342 { 343 "candidateUpdate", 344 "f9010609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8a4435f9f2200000000000000000000000000000000000000000000000000000000000000600000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d824000000000000000000000000000000000000000000000000000000000000000474657374000000000000000000000000000000000000000000000000000000008224c6a04df6545da871debef84476198e76167d4dfe6fb83098a5a49dbab734352f20f1a0220686494f8b09751bbeb5c63729e7ecc5c504f952c67e926461db98588854b6", 345 9, 346 21000, 347 "0", 348 "0", 349 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 350 _evmNetworkID, 351 iotextypes.Encoding_ETHEREUM_EIP155, 352 164, 353 "7a8d96d35c939bf1634d587b1f471c0f3f96ba750d64d43289c9eef267718ef0", 354 "04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b", 355 "1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e", 356 }, 357 { 358 "rewardingClaim", 359 "f8c6806482520894a576c141e5659137ddda4223d209d4744b2106be80b8642df163ef0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a03d62943431b8ca0e8ea0a9c79dc8f64df14c965ca5486da124804013778ed566a065956b185116b65cec0ec9bcf9539e924784a4b448190b0aa9d017f1719be921", 360 0, 361 21000, 362 "100", 363 "0", 364 "0xA576C141e5659137ddDa4223d209d4744b2106BE", 365 _evmNetworkID, 366 iotextypes.Encoding_ETHEREUM_EIP155, 367 100, 368 "4d26d0736ebd9e69bd5994f3730b05a2d48c810b3bb54818be65d02004cf4ff4", 369 "04830579b50e01602c2015c24e72fbc48bca1cca1e601b119ca73abe2e0b5bd61fcb7874567e091030d6b644f927445d80e00b3f9ca0c566c21c30615e94c343da", 370 "8d38efe45794d7fceea10b2262c23c12245959db", 371 }, 372 { 373 "rewardingDeposit", 374 "f8c6016482520894a576c141e5659137ddda4223d209d4744b2106be80b86427852a6b0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a013b7679dbabcb0f97b93942436f5072cca3c7fe43451a8fedcdf3c84c1344e1da02af4cc67594c0200b59f4e30ba149af15e546acbfc69fa31f14e8788ab063d85", 375 1, 376 21000, 377 "100", 378 "0", 379 "0xA576C141e5659137ddDa4223d209d4744b2106BE", 380 _evmNetworkID, 381 iotextypes.Encoding_ETHEREUM_EIP155, 382 100, 383 "842fea9a292c0bc7a1e05a14a8255ed8dc945fdae7c01a6b70f5213ebe35583b", 384 "04830579b50e01602c2015c24e72fbc48bca1cca1e601b119ca73abe2e0b5bd61fcb7874567e091030d6b644f927445d80e00b3f9ca0c566c21c30615e94c343da", 385 "8d38efe45794d7fceea10b2262c23c12245959db", 386 }, 387 { 388 "candidateActivate", 389 "f88a7885e8d4a510008252089404c22afae6a03438b8fed74cb1cf441168df3f1280a4ef68b1a400000000000000000000000000000000000000000000000000000000000000018224c6a05d21ebb92203797ce49a95febe4430cfdfd32deb9284c80fee5d600124a77791a05ac4871b1b1200433f197aee068007b52f2b096e27fe473874ceab89661fad2a", 390 120, 391 21000, 392 "1000000000000", 393 "0", 394 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 395 _evmNetworkID, 396 iotextypes.Encoding_ETHEREUM_EIP155, 397 36, 398 "db61959a804781ea9da78d6d4ce6054e1ea940ae4a2cac3853f5262728a9369e", 399 "049ea260dc05a824a8a7e92d3b87e47ce06384e1eee15d446494a20d299c1bd11900edc2df5697aa00b2256c286193239f83740d079b032b9fbe085b791fa10950", 400 "065e1164818487818e6ba714e8d80b91718ad758", 401 }, 402 { 403 "candidateEndorsement", 404 "f8ab7885e8d4a510008252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8448a8a5d51000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018224c5a0cb0c5d443925b98776645793fe8bfdeb34ca1d364d1c389521f5a4c715a42a91a07c1bb620307a78fb463bb8204a43d4bf32acd6efed0cb6b7c00eb7ae13da1ad6", 405 120, 406 21000, 407 "1000000000000", 408 "0", 409 "0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12", 410 _evmNetworkID, 411 iotextypes.Encoding_ETHEREUM_EIP155, 412 68, 413 "008d08ae3327ae395fdc0b16497e181c4eb6633cf796c174e8819cbb2a29194c", 414 "049ea260dc05a824a8a7e92d3b87e47ce06384e1eee15d446494a20d299c1bd11900edc2df5697aa00b2256c286193239f83740d079b032b9fbe085b791fa10950", 415 "065e1164818487818e6ba714e8d80b91718ad758", 416 }, 417 { 418 "unprotected", 419 deterministicDeploymentTx, 420 0, 421 100000, 422 "100000000000", 423 "0", 424 EmptyAddress, 425 0, 426 iotextypes.Encoding_ETHEREUM_UNPROTECTED, 427 83, 428 "eddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26", 429 "040a98b1acb38ed9cd8d0e8f1f03b1588bae140586f8a8049197b65013a3c17690151ae422e3fdfb26be2e6a4465b1f9cf5c26a5635109929a0d0a11734124d50a", 430 "3fab184622dc19b6109349b94811493bf2a45362", 431 }, 432 } 433 ) 434 435 func TestNewEthSignerError(t *testing.T) { 436 require := require.New(t) 437 singer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_ACCESSLIST, 1) 438 require.ErrorIs(err, ErrInvalidAct) 439 require.Nil(singer) 440 441 tx := types.NewTx(&types.DynamicFeeTx{ 442 To: nil, 443 Nonce: 4, 444 Value: big.NewInt(4), 445 Gas: 4, 446 GasTipCap: big.NewInt(44), 447 GasFeeCap: big.NewInt(1045), 448 }) 449 _, _, _, err = ExtractTypeSigPubkey(tx) 450 require.ErrorIs(err, ErrNotSupported) 451 } 452 453 func TestEthTxDecodeVerify(t *testing.T) { 454 require := require.New(t) 455 456 for _, v := range rlpTests { 457 // decode received RLP tx 458 tx, err := DecodeEtherTx(v.raw) 459 require.NoError(err) 460 encoding, sig, pubkey, err := ExtractTypeSigPubkey(tx) 461 require.Equal(v.encoding, encoding) 462 V, _, _ := tx.RawSignatureValues() 463 recID := V.Uint64() 464 if encoding == iotextypes.Encoding_ETHEREUM_EIP155 { 465 require.EqualValues(types.LegacyTxType, tx.Type()) 466 require.True(tx.Protected()) 467 require.Less(uint64(28), recID) 468 } else if encoding == iotextypes.Encoding_ETHEREUM_UNPROTECTED { 469 require.EqualValues(types.LegacyTxType, tx.Type()) 470 require.False(tx.Protected()) 471 require.Zero(tx.ChainId().Uint64()) 472 // unprotected tx has V = 27, 28 473 require.True(27 == recID || 28 == recID) 474 require.True(27 == sig[64] || 28 == sig[64]) 475 } 476 require.EqualValues(v.chainID, tx.ChainId().Uint64()) 477 require.Equal(v.pubkey, pubkey.HexString()) 478 require.Equal(v.pkhash, hex.EncodeToString(pubkey.Hash())) 479 480 // convert to our Execution 481 pb := &iotextypes.Action{ 482 Encoding: encoding, 483 } 484 pb.Core = convertToNativeProto(tx, v.actType) 485 pb.SenderPubKey = pubkey.Bytes() 486 pb.Signature = sig 487 488 // send on wire 489 bs, err := proto.Marshal(pb) 490 require.NoError(err) 491 492 // receive from API 493 proto.Unmarshal(bs, pb) 494 selp, err := (&Deserializer{}).SetEvmNetworkID(v.chainID).ActionToSealedEnvelope(pb) 495 require.NoError(err) 496 act, ok := selp.Action().(EthCompatibleAction) 497 require.True(ok) 498 rlpTx, err := act.ToEthTx(uint32(tx.ChainId().Uint64())) 499 require.NoError(err) 500 501 // verify against original tx 502 require.Equal(v.nonce, rlpTx.Nonce()) 503 require.Equal(v.price, rlpTx.GasPrice().String()) 504 require.Equal(v.limit, rlpTx.Gas()) 505 if v.to == "" { 506 require.Nil(rlpTx.To()) 507 } else { 508 require.Equal(v.to, rlpTx.To().Hex()) 509 } 510 require.Equal(v.amount, rlpTx.Value().String()) 511 require.Equal(v.dataLen, len(rlpTx.Data())) 512 h, err := selp.Hash() 513 require.NoError(err) 514 require.Equal(v.hash, hex.EncodeToString(h[:])) 515 require.Equal(pubkey, selp.SrcPubkey()) 516 require.True(bytes.Equal(sig, selp.signature)) 517 raw, err := selp.envelopeHash() 518 require.NoError(err) 519 signer, err := NewEthSigner(encoding, uint32(tx.ChainId().Uint64())) 520 require.NoError(err) 521 rawHash := signer.Hash(tx) 522 require.True(bytes.Equal(rawHash[:], raw[:])) 523 require.NotEqual(raw, h) 524 require.NoError(selp.VerifySignature()) 525 } 526 } 527 528 func convertToNativeProto(tx *types.Transaction, actType string) *iotextypes.ActionCore { 529 elpBuilder := &EnvelopeBuilder{} 530 elpBuilder.SetGasLimit(tx.Gas()).SetGasPrice(tx.GasPrice()).SetNonce(tx.Nonce()) 531 switch actType { 532 case "transfer": 533 elp, _ := elpBuilder.BuildTransfer(tx) 534 return elp.Proto() 535 case "execution", "unprotected", "accesslist": 536 elp, _ := elpBuilder.BuildExecution(tx) 537 return elp.Proto() 538 case "stakeCreate", "stakeAddDeposit", "changeCandidate", "unstake", "withdrawStake", "restake", 539 "transferStake", "candidateRegister", "candidateUpdate", "candidateActivate", "candidateEndorsement": 540 elp, _ := elpBuilder.BuildStakingAction(tx) 541 return elp.Proto() 542 case "rewardingClaim", "rewardingDeposit": 543 elp, _ := elpBuilder.BuildRewardingAction(tx) 544 return elp.Proto() 545 default: 546 panic("unsupported") 547 } 548 } 549 550 func TestIssue3944(t *testing.T) { 551 r := require.New(t) 552 // the sample tx below is the web3 format tx on the testnet: 553 // https://testnet.iotexscan.io/tx/fcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285 554 // or you can get it using ethclient code: 555 // { 556 // cli, _ := ethclient.Dial("https://babel-api.testnet.iotex.io") 557 // tx, _, err := cli.TransactionByHash(context.Background(), common.HexToHash("0xfcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285")) 558 // } 559 var ( 560 hash = "0xfcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285" 561 data, _ = hex.DecodeString("f3fef3a3000000000000000000000000fdff3eafde9a0cc42d18aab2a7454b1105f19edf00000000000000000000000000000000000000000000002086ac351052600000") 562 to = common.HexToAddress("0xd313b3131e238C635f2fE4a84EaDaD71b3ed25fa") 563 sig, _ = hex.DecodeString("adff1da88c93f4e80c27bab0d613147fb7aeeed6e976231695de52cd9ac5aa8a3094e02759b838514f8376e05ceb266badc791ac2e7045ee7c15e58fc626980b1b") 564 ) 565 tx := types.NewTx(&types.LegacyTx{ 566 Nonce: 83, 567 To: &to, 568 Value: new(big.Int), 569 Gas: 39295, 570 GasPrice: big.NewInt(1000000000000), 571 Data: data, 572 V: big.NewInt(int64(sig[64])), 573 R: new(big.Int).SetBytes(sig[:32]), 574 S: new(big.Int).SetBytes(sig[32:64]), 575 }) 576 577 r.EqualValues(types.LegacyTxType, tx.Type()) 578 r.False(tx.Protected()) 579 v, q, s := tx.RawSignatureValues() 580 r.Equal(sig[:32], q.Bytes()) 581 r.Equal(sig[32:64], s.Bytes()) 582 r.Equal("1b", v.Text(16)) 583 r.NotEqual(hash, tx.Hash().Hex()) // hash does not match with wrong V value in signature 584 585 signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, 4690) 586 r.NoError(err) 587 tx1, err := RawTxToSignedTx(tx, signer, sig) 588 r.NoError(err) 589 r.True(tx1.Protected()) 590 r.EqualValues(4690, tx1.ChainId().Uint64()) 591 v, q, s = tx1.RawSignatureValues() 592 r.Equal(sig[:32], q.Bytes()) 593 r.Equal(sig[32:64], s.Bytes()) 594 r.Equal("9415", v.String()) // this is the correct V value corresponding to chainID = 4690 595 r.Equal(hash, tx1.Hash().Hex()) 596 } 597 598 func TestBackwardComp(t *testing.T) { 599 r := require.New(t) 600 for _, chainID := range []uint32{_evmNetworkID, _evmNetworkID + 1, 31337, 0} { 601 _, _, _, err := DecodeRawTx(deterministicDeploymentTx, chainID) 602 r.Equal(crypto.ErrInvalidKey, err) 603 _, _, _, err = DecodeRawTx(accessListTx, chainID) 604 r.ErrorContains(err, "typed transaction too short") 605 } 606 }