Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth/tx: update tx initcode cost for shanghai #237

Merged
merged 5 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,15 @@ jobs:
sudo apt-get update
sudo apt-get install ethereum solc libyaml-dev
if: startsWith(matrix.os, 'Ubuntu')
- name: Patch Geth # https://github.com/ethereum/go-ethereum/pull/27360
run: |
git clone https://github.com/q9f/go-ethereum.git -b q9f/params/shanghai
pushd go-ethereum/
make geth
popd
- name: Run Geth
run: |
geth --dev --http --ipcpath /tmp/geth.ipc &
disown &
./go-ethereum/build/bin/geth --dev --http --ipcpath /tmp/geth.ipc &
- name: Gem Dependencies
run: |
git submodule update --init
Expand Down
2 changes: 1 addition & 1 deletion lib/eth/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def transact(contract, function, *args, **kwargs)
gas_limit = if kwargs[:gas_limit]
kwargs[:gas_limit]
else
Tx.estimate_intrinsic_gas(contract.bin) + Tx::CREATE_GAS
Tx.estimate_intrinsic_gas(contract.bin)
end
fun = contract.functions.select { |func| func.name == function }[0]
params = {
Expand Down
11 changes: 9 additions & 2 deletions lib/eth/tx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class ParameterError < TypeError; end
# The calldata gas cost of a zero byte.
COST_ZERO_BYTE = 4.freeze

# The initcode gas cost for each word (32 bytes).
COST_INITCODE_WORD = 2.freeze

# The access list gas cost of a storage key as per EIP-2930.
COST_STORAGE_KEY = 1_900.freeze

Expand Down Expand Up @@ -156,7 +159,7 @@ def unsigned_copy(tx)
end

# Estimates intrinsic gas for provided call data (EIP-2028) and
# access lists (EIP-2930).
# access lists (EIP-2930). Respects initcode word cost (EIP-3860).
#
# @param data [String] the call data.
# @param list [Array] the access list.
Expand All @@ -173,6 +176,10 @@ def estimate_intrinsic_gas(data = "", list = [])
# count non-zero bytes
none = data.size - zero
gas += none * COST_NON_ZERO_BYTE

# count "words" as per EIP-3860
word_count = (data.length.to_f / 32.0).ceil
gas += word_count * COST_INITCODE_WORD
end
unless list.nil? or list.empty?
list.each do |entry|
Expand All @@ -187,7 +194,7 @@ def estimate_intrinsic_gas(data = "", list = [])
end
end
end
return gas
return gas.to_i
end

# Validates the common transaction fields such as nonce, gas limit,
Expand Down
20 changes: 10 additions & 10 deletions spec/eth/tx/eip2930_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@
sample = Tx.new({
nonce: 0,
gas_price: 0x0BA43B7400,
gas_limit: 0x073a0,
gas_limit: 0x07b50,
to: "0x7917bc33eea648809c285607579c9919fb864f8f",
value: 0x03BAF82D03A000,
access_list: list,
Expand All @@ -257,8 +257,8 @@
expected_address = Address.new "8d900bfa2353548a4631be870f99939575551b60"

# a secp256k1 signature over keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]))
expected_sign_data = "01f89d0180850ba43b74008273a0947917bc33eea648809c285607579c9919fb864f8f8703baf82d03a00080f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c0"
expected_sign_hash = "c129e3830bdfca2973a26d718b92b5f10564b2f57a02fa0f3888de3273d5b974"
expected_sign_data = "01f89d0180850ba43b7400827b50947917bc33eea648809c285607579c9919fb864f8f8703baf82d03a00080f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c0"
expected_sign_hash = "81f7bf86cf365f50ef2a9663c4f3001c22394ccd891cd1be8ef59af94d2b1b45"

# first byte is type 01 as per EIP-2930
expect(Util.bin_to_hex (sample.unsigned_encoded)[0, 1]).to eq "01"
Expand Down Expand Up @@ -288,15 +288,15 @@
-4153010759215853346544872368790226810347211436084119296615430562753409734914,
]
}
subject(:expected_hex) { "01f90181018001827b448080b8c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000003ea1e26a2119b038eaf9b27e65cdb401502ae7a43d8bfb1368aee2693eb325af9f81244b19304b087b4941a1e892da50bd48dfe1f6d17aad7aff1c87e8481f30395a1595a07b483032affed044e698bf7c43a6fe000000000000000000000000000000000000000000000000000000000000000d4c6f72656d2c20497073756d2100000000000000000000000000000000000000f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c001a047abf8694b14a2d84b5b8e0d8270e79f7772ac71419f5770ce7318bfaae952dba0141d4c6e7cad5af300a1c90924704394a09f9f3476b7c1a219ee799ffb91e765" }
subject(:expected_hash) { "800a8f4816dffee600600cd36f202b14e2d802ae7369aafae9ecb0e5c4906cbc" }
subject(:expected_hex) { "01f90181018001827b508080b8c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000003ea1e26a2119b038eaf9b27e65cdb401502ae7a43d8bfb1368aee2693eb325af9f81244b19304b087b4941a1e892da50bd48dfe1f6d17aad7aff1c87e8481f30395a1595a07b483032affed044e698bf7c43a6fe000000000000000000000000000000000000000000000000000000000000000d4c6f72656d2c20497073756d2100000000000000000000000000000000000000f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c080a001101750fe4fc89a413e65c7e9ef459180742ef68bda055c35761c84302cad13a037dd31afd4c84fb46fec9120934247662399aa053ce7b5b724275239b15ee3ad" }
subject(:expected_hash) { "3559540a9e9a228a240643f2f3b3823e5c8ffa41a5d8f37907ea91d50ef59979" }

it "can create transactions with binary data" do
abi = Abi.encode types, args
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 31_556,
gas_limit: 31_568,
data: abi,
access_list: list,
})
Expand All @@ -322,7 +322,7 @@
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 31_556,
gas_limit: 31_568,
data: hex,
access_list: list,
})
Expand All @@ -349,13 +349,13 @@
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 29_808,
gas_limit: 29_810,
data: lorem,
access_list: list,
})
some.sign cow
expect(some.hex).to eq "01f8cd01800182747080808d4c6f72656d2c20497073756d21f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c080a0aa8fb1b77d26ee25034e7012fd5098c2ffb46ec26f852f492adf38d0ce4480a3a019b93db449c5320f237d6ffa2612055afb8b4286c5f7fe9123c78a287b61af91"
expect(some.hash).to eq "8a3ac899feaf2260701cd92fb094924b0453552286e867f56c4d0c41d1214c25"
expect(some.hex).to eq "01f8cd01800182747280808d4c6f72656d2c20497073756d21f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007d694bb9bc244d798123fde783fcc1c72d3bb8c189413c080a017c081b8c851fa7df558054e93539f20b0937aafed06586a2ad59824d52a6f55a00f40033eec8ff5ce9d37270a4170a5d2349142d1f5d0df5064439f60ee6c78be"
expect(some.hash).to eq "52d5c664c2c2da1970f192a2bc8097f22a77035fceef26a9bd00a00473fe035b"

# expect to match both decoded transaction and decoded abi
other = Tx.decode some.hex
Expand Down
44 changes: 22 additions & 22 deletions spec/eth/tx/legacy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@
}
subject(:cow) { Key.new(priv: Util.keccak256("cow")) }

# ref https://goerli.etherscan.io/tx/0x1975df4e715ce4af46c604e3fafb763a51cc133a42e43566779b4d5608bb4af1
# ref https://sepolia.etherscan.io/tx/0x7613b4de482fcff616e11907d16ddba1aa950a020ec58e99ab28ba0c5926ec53
subject(:legacy) {
Tx.new(
{
nonce: 1,
gas_price: 40 * Unit::GWEI,
gas_limit: 21576,
gas_limit: 21580,
to: "0xcaa29806044a08e533963b2e573c1230a2cd9a2d",
value: BigDecimal("0.123456789012345678") * Unit::ETHER,
data: "Lorem Ipsum Ruby Ethereum Test 1-2-3",
},
Chain::GOERLI
Chain::SEPOLIA
)
}

# ref https://goerli.etherscan.io/tx/0x047e319fc8e587a77f6e9a13c30d90b5a741d93e8b35a54b12c91d6149eda359
# ref https://sepolia.etherscan.io/tx/0x01fa6584df6326dc503ca809c9c4643cd753ba8ae63473a9994770f403cda447
subject(:ruby) {
Tx.new(
{
Expand All @@ -38,12 +38,12 @@
value: 0.0069 * Unit::ETHER,
data: "Foo Bar Ruby Ethereum",
},
Chain::GOERLI
Chain::SEPOLIA
)
}

# ref https://goerli.etherscan.io/address/0x4762119a7249823d18aec7eab73258b2d5061dd8
subject(:testnet) { Key.new(priv: "0xc6c633f85d3f9a4705623b1d9bd1122a1a9196cd53dd352505e895fcbb8452ef") }
# ref https://sepolia.etherscan.io/address/0xc3c8fd0f04b629c5e2297b79c54dd57b85a721e3
subject(:testnet) { Key.new(priv: "0xa0d1f18547caa1fb5c121c862d8ac66d9d6afe0afa79b291ca197e64fdccfd23") }

describe ".decode" do
it "decodes the first mainnet transaction" do
Expand Down Expand Up @@ -76,11 +76,11 @@
expect(tx.hash).to eq expected_hash
end

it "decodes a known goerli transaction signed by ruby eth gem" do
it "decodes a known sepolia transaction signed by ruby eth gem" do

# ref https://goerli.etherscan.io/getRawTx?tx=0x047e319fc8e587a77f6e9a13c30d90b5a741d93e8b35a54b12c91d6149eda359
expected_hex = "0xf880038509c76524008259d894caa29806044a08e533963b2e573c1230a2cd9a2d8718838370f3400095466f6f20426172205275627920457468657265756d2ea0a0133bf9a770032e18a2ce0eda0d8562abbd88920d696d02373e901967f9956da075e6ce3e86db8391524a7dff0331e90c2bf18cedfbd4164f177a86c53e5be4fa"
expected_hash = "0x047e319fc8e587a77f6e9a13c30d90b5a741d93e8b35a54b12c91d6149eda359"
# ref https://sepolia.etherscan.io/getRawTx?tx=0x01fa6584df6326dc503ca809c9c4643cd753ba8ae63473a9994770f403cda447
expected_hex = "0xf884038509c76524008259d894caa29806044a08e533963b2e573c1230a2cd9a2d8718838370f3400095466f6f20426172205275627920457468657265756d8401546d72a0980cf5d1c20ed6a44a57b4ec70301da608247013be59be740e471579a16b9963a053a2e3b95f666c38ec26c0be6105affd23c037c67277ed920aae79f93c020fa6"
expected_hash = "0x01fa6584df6326dc503ca809c9c4643cd753ba8ae63473a9994770f403cda447"
decoded = Tx.decode(expected_hex)
expect(decoded.hex).to eq Util.remove_hex_prefix expected_hex
expect(decoded.hash).to eq Util.remove_hex_prefix expected_hash
Expand Down Expand Up @@ -167,7 +167,7 @@

it "it does not sign a transaction twice" do
expect { legacy.hash }.to raise_error StandardError, "Transaction is not signed!"
expect(testnet.address.to_s).to eq "0x4762119a7249823D18aec7EAB73258B2D5061Dd8"
expect(testnet.address.to_s).to eq "0xC3c8Fd0f04B629c5E2297b79c54DD57b85A721e3"
legacy.sign(testnet)
expect { legacy.sign(testnet) }.to raise_error StandardError, "Transaction is already signed!"
end
Expand Down Expand Up @@ -198,7 +198,7 @@
it "encodes a known goerli transaction" do
expect { legacy.encoded }.to raise_error StandardError, "Transaction is not signed!"
legacy.sign(testnet)
expect(legacy.encoded).to eq "\xF8\x90\x01\x85\tP/\x90\x00\x82TH\x94\xCA\xA2\x98\x06\x04J\b\xE53\x96;.W<\x120\xA2\xCD\x9A-\x88\x01\xB6\x9BK\xA60\xF3N\xA4Lorem Ipsum Ruby Ethereum Test 1-2-3.\xA0\xFBM0\x8F=?\x97p\xF2e.\xF4\x0E\xA86\x9A\xB3r\xE5\x9B\xAD\x81O\xB2'\xFA\xE1\xFD\xFD\xFAM:\xA0f\xC8\xA2\xA2\xA2\xAB\xCD9\e\xAC\x869\x99Z\x10\xF1Tj\x87>\xF5\xB4R\xBF\xE5\xFC6y\x01\xD9\xF4\xAB"
expect(legacy.encoded).to eq "\xF8\x94\x01\x85\tP/\x90\x00\x82TL\x94\xCA\xA2\x98\x06\x04J\b\xE53\x96;.W<\x120\xA2\xCD\x9A-\x88\x01\xB6\x9BK\xA60\xF3N\xA4Lorem Ipsum Ruby Ethereum Test 1-2-3\x84\x01Tmr\xA0\x9Eh\x00\x9D\xBA<\x05MyVM\x82W\x86\xE9Z\xE7t\xF2\xE5\xB2\xF4\xD7_\xA5X\x88=\v#_\x82\xA02\xDCc\t\xDD\xD9)\xF5\xB1\xFC\xE3\xC9\xEC\x04\x13\aR\xF4\n}\xA2\xF2\x82\xE7x\b\xD6\x97\x93\xF6F\xEF"
end
end

Expand All @@ -212,7 +212,7 @@
it "hexes a known goerli transaction" do
expect { legacy.hex }.to raise_error StandardError, "Transaction is not signed!"
legacy.sign(testnet)
expect(legacy.hex).to eq "f890018509502f900082544894caa29806044a08e533963b2e573c1230a2cd9a2d8801b69b4ba630f34ea44c6f72656d20497073756d205275627920457468657265756d205465737420312d322d332ea0fb4d308f3d3f9770f2652ef40ea8369ab372e59bad814fb227fae1fdfdfa4d3aa066c8a2a2a2abcd391bac8639995a10f1546a873ef5b452bfe5fc367901d9f4ab"
expect(legacy.hex).to eq "f894018509502f900082544c94caa29806044a08e533963b2e573c1230a2cd9a2d8801b69b4ba630f34ea44c6f72656d20497073756d205275627920457468657265756d205465737420312d322d338401546d72a09e68009dba3c054d79564d825786e95ae774f2e5b2f4d75fa558883d0b235f82a032dc6309ddd929f5b1fce3c9ec04130752f40a7da2f282e77808d69793f646ef"
end
end

Expand All @@ -226,7 +226,7 @@
it "hashes a known goerli transaction" do
expect { legacy.hash }.to raise_error StandardError, "Transaction is not signed!"
legacy.sign(testnet)
expect(legacy.hash).to eq "1975df4e715ce4af46c604e3fafb763a51cc133a42e43566779b4d5608bb4af1"
expect(legacy.hash).to eq "7613b4de482fcff616e11907d16ddba1aa950a020ec58e99ab28ba0c5926ec53"
end
end

Expand Down Expand Up @@ -300,15 +300,15 @@
-4153010759215853346544872368790226810347211436084119296615430562753409734914,
]
}
subject(:expected_hex) { "f9010c80018259ac8080b8c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000003ea1e26a2119b038eaf9b27e65cdb401502ae7a43d8bfb1368aee2693eb325af9f81244b19304b087b4941a1e892da50bd48dfe1f6d17aad7aff1c87e8481f30395a1595a07b483032affed044e698bf7c43a6fe000000000000000000000000000000000000000000000000000000000000000d4c6f72656d2c20497073756d210000000000000000000000000000000000000026a0b06ef4fc47e80f9fc70143b558dfa31d6dae04661f37715b982718f8185aefa3a032a8b187b43ae4af3755e7158f7cbb9585485e05ffdd38fe3343767a61730026" }
subject(:expected_hash) { "3ac265b9741844e04f9ac8436469393a44d89d6fe20343fc9ea60f0f377db9ec" }
subject(:expected_hex) { "f9010c80018259b88080b8c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000003ea1e26a2119b038eaf9b27e65cdb401502ae7a43d8bfb1368aee2693eb325af9f81244b19304b087b4941a1e892da50bd48dfe1f6d17aad7aff1c87e8481f30395a1595a07b483032affed044e698bf7c43a6fe000000000000000000000000000000000000000000000000000000000000000d4c6f72656d2c20497073756d210000000000000000000000000000000000000026a081bf91ec0984c884c7d8afe094743d30c73e08c6d6c2da497dbb75193dd0cd07a059189d3f14ea3e0eccc6240e019f09d6b277e1525a0aa7e5bdca9e444f6f4630" }
subject(:expected_hash) { "045ef9de4ed1aee2274be36a92db5293063bee674ec46ad94ad4d057250db536" }

it "can create transactions with binary data" do
abi = Abi.encode types, args
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 22_956,
gas_limit: 22_968,
data: abi,
})

Expand All @@ -332,7 +332,7 @@
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 22_956,
gas_limit: 22_968,
data: hex,
})

Expand All @@ -357,12 +357,12 @@
some = Tx.new({
nonce: 0,
gas_price: 1,
gas_limit: 21_208,
gas_limit: 21_210,
data: lorem,
})
some.sign cow
expect(some.hex).to eq "f85880018252d880808d4c6f72656d2c20497073756d2125a08540db1627dd415d4b53f2d0b7835510ab9cfc77ad40a785e7e0dc6ec63cef79a02822730ee77dfddee349d720e3cfa955b38f7ffb9e482e4c15931bb9cca0c33c"
expect(some.hash).to eq "37aa7c93ffcbc92bcd016796ae231ea2ddce5c0daa5f5646784d3cbb9b6cff3b"
expect(some.hex).to eq "f85880018252da80808d4c6f72656d2c20497073756d2125a0121ceae143464734a25416294fd324e8a5a8578bbad84b7044a2f84b2ae0c0e8a00f72e5a58b1c40a9484026137e69a00746d613bd9445d767a7d7a305a2947e2d"
expect(some.hash).to eq "43bbce3dc6bc845bfbf052df40bfbf20086eb6f983c5aacf9a964a0cc6b1c22a"

# expect to match both decoded transaction and decoded abi
other = Tx.decode some.hex
Expand Down
Loading