diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go index ba7db9039..0c05e1279 100644 --- a/cmd/devp2p/internal/ethtest/snap.go +++ b/cmd/devp2p/internal/ethtest/snap.go @@ -87,9 +87,9 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { root: root, startingHash: zero, limitHash: ffHash, - expAccounts: 67, + expAccounts: 68, expFirst: firstKey, - expLast: common.HexToHash("0x5602444769b5fd1ddfca48e3c38f2ecad326fe2433f22b90f6566a38496bd426"), + expLast: common.HexToHash("0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"), desc: "In this test, we request the entire state range, but limit the response to 4000 bytes.", }, { @@ -99,7 +99,7 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { limitHash: ffHash, expAccounts: 50, expFirst: firstKey, - expLast: common.HexToHash("0x420a83d9891f19593cdda9b31bb3b450e960fa87042dd428a7fa5ee69db02c75"), + expLast: common.HexToHash("0x4363d332a0d4df8582a84932729892387c623fe1ec42e2cfcbe85c183ed98e0e"), desc: "In this test, we request the entire state range, but limit the response to 3000 bytes.", }, { @@ -109,7 +109,7 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { limitHash: ffHash, expAccounts: 34, expFirst: firstKey, - expLast: common.HexToHash("0x2d425481284fbb1874a2c55d81564f371543b3b8f7450e860bc5381ba47b465f"), + expLast: common.HexToHash("0x2de4bdbddcfbb9c3e195dae6b45f9c38daff897e926764bf34887fb0db5c3284"), desc: "In this test, we request the entire state range, but limit the response to 2000 bytes.", }, { @@ -178,9 +178,9 @@ The server should return the first available account.`, root: root, startingHash: firstKey, limitHash: ffHash, - expAccounts: 67, + expAccounts: 68, expFirst: firstKey, - expLast: common.HexToHash("0x5602444769b5fd1ddfca48e3c38f2ecad326fe2433f22b90f6566a38496bd426"), + expLast: common.HexToHash("0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"), desc: `In this test, startingHash is exactly the first available account key. The server should return the first available account of the state as the first item.`, }, @@ -191,7 +191,7 @@ The server should return the first available account of the state as the first i limitHash: ffHash, expAccounts: 68, expFirst: secondKey, - expLast: common.HexToHash("0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"), + expLast: common.HexToHash("0x59a7c8818f1c16b298a054020dc7c3f403a970d1d1db33f9478b1c36e3a2e509"), desc: `In this test, startingHash is after the first available key. The server should return the second account of the state as the first item.`, }, @@ -229,7 +229,7 @@ server to return no data because genesis is older than 127 blocks.`, limitHash: ffHash, expAccounts: 66, expFirst: firstKey, - expLast: common.HexToHash("0x792cc9f20a61c16646d5b6136693e7789549adb7d8e35503d0004130ea6528b0"), + expLast: common.HexToHash("0x7963685967117ffb6fd019663dc9e782ebb1234a38501bffc2eb5380f8dc303b"), desc: `This test requests data at a state root that is 127 blocks old. We expect the server to have this state available.`, }, @@ -661,7 +661,7 @@ The server should reject the request.`, // It's a bit unfortunate these are hard-coded, but the result depends on // a lot of aspects of the state trie and can't be guessed in a simple // way. So you'll have to update this when the test chain is changed. - common.HexToHash("0x9ac5b414913a065dfc5d56f7c20b5ee000e2cb6588e1a3ade1dd8c883d8e0db1"), + common.HexToHash("0x09d0a5a624c6cea221c43c9bfc83787d3098ffb81b5554464526e7f7a1e0a826"), common.HexToHash("0x2b8c08122de89dadd4ca2c72f2cbc5e109b792bd82787a343713e3b632a77556"), empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, @@ -683,7 +683,7 @@ The server should reject the request.`, expHashes: []common.Hash{ empty, common.HexToHash("0x2b8c08122de89dadd4ca2c72f2cbc5e109b792bd82787a343713e3b632a77556"), - common.HexToHash("0x9ac5b414913a065dfc5d56f7c20b5ee000e2cb6588e1a3ade1dd8c883d8e0db1"), + common.HexToHash("0x09d0a5a624c6cea221c43c9bfc83787d3098ffb81b5554464526e7f7a1e0a826"), }, }, diff --git a/cmd/devp2p/internal/ethtest/testdata/chain.rlp b/cmd/devp2p/internal/ethtest/testdata/chain.rlp index bb0373497..8db90045b 100644 Binary files a/cmd/devp2p/internal/ethtest/testdata/chain.rlp and b/cmd/devp2p/internal/ethtest/testdata/chain.rlp differ diff --git a/cmd/devp2p/internal/ethtest/testdata/genesis.json b/cmd/devp2p/internal/ethtest/testdata/genesis.json index 6030b3c3b..b773920d3 100644 --- a/cmd/devp2p/internal/ethtest/testdata/genesis.json +++ b/cmd/devp2p/internal/ethtest/testdata/genesis.json @@ -26,10 +26,10 @@ }, "init": { "validators": [ - "0x7a2b5390bb632269133d3b7eda466b4b44bf2762" + "0x45dfd9f6da52abaee54ad49226c698e45b2f3777" ], "blsPublicKeys": [ - "0x97c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558ef7087a0785870202c45dd49c5de147b3" + "0x92272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261fbfc5578c46407b94ba8dcdf6f8c926b" ] }, "systemContracts": { @@ -37,13 +37,13 @@ "address": "0x0000000000000000000000000000000000001001", "version": "v1", "params": { - "blsPublicKeys": "0x97c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558ef7087a0785870202c45dd49c5de147b3", + "blsPublicKeys": "0x92272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261fbfc5578c46407b94ba8dcdf6f8c926b", "expiry": "604800", "maxProposals": "3", "memberVersion": "1", - "members": "0x7a2B5390bb632269133D3B7Eda466b4b44bf2762", + "members": "0x45dFD9F6dA52AbaeE54AD49226c698e45b2f3777", "quorum": "1", - "validators": "0x7a2B5390bb632269133D3B7Eda466b4b44bf2762" + "validators": "0x45dFD9F6dA52AbaeE54AD49226c698e45b2f3777" } }, "nativeCoinAdapter": { @@ -88,20 +88,14 @@ "govCouncil": { "address": "0x0000000000000000000000000000000000001004", "version": "v1", - "params": { - "expiry": "604800", - "maxProposals": "3", - "memberVersion": "1", - "members": "0xaa5faa65e9cc0f74a85b6fdfb5f6991f5c094697", - "quorum": "1" - } + "params": null } } } }, "nonce": "0x0", "timestamp": "0x0", - "extraData": "0xf860808080c0c080c0c086048c27395000f84fdad9947a2b5390bb632269133d3b7eda466b4b44bf2762831cfde0c180f1b097c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558ef7087a0785870202c45dd49c5de147b3", + "extraData": "0xf860808080c0c080c0c086048c27395000f84fdad99445dfd9f6da52abaee54ad49226c698e45b2f3777831cfde0c180f1b092272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261fbfc5578c46407b94ba8dcdf6f8c926b", "gasLimit": "0x23f3e20", "difficulty": "0x1", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -133,19 +127,19 @@ "0x0000000000000000000000000000000000000000000000000000000000000032": "0x0000000000000000000000000000000000000000000000000000000000b00001", "0x0000000000000000000000000000000000000000000000000000000000000033": "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000039": "0x0000000000000000000000000000000000000000000000000000048c27395000", - "0x028dcfa4bfbc0247b35b0bda5a23aa67d17cdd3ac2268b9991fddf4970ecedd5": "0x97c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558e", - "0x028dcfa4bfbc0247b35b0bda5a23aa67d17cdd3ac2268b9991fddf4970ecedd6": "0xf7087a0785870202c45dd49c5de147b300000000000000000000000000000000", - "0x1e69254cd49a2c45945d52e976b9871368a351652786da8a1f1463e2e665f936": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0b851d8cc2d7feaca604f32212764c413d624fc7c40f484d1008902bf6d8c4d4": "0x00000000000000000000000045dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x36f6cb310a5204ca809a30b476706146d10378ba8ac1e6fb04dbfdab6fa18366": "0x92272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261", + "0x36f6cb310a5204ca809a30b476706146d10378ba8ac1e6fb04dbfdab6fa18367": "0xfbfc5578c46407b94ba8dcdf6f8c926b00000000000000000000000000000000", "0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x3e8da299fe59cecc53e28d470b241fd34828ffde97ea9bb1219f65edac4f64e1": "0x0000000000000000000000000000000000000000000000000000000000000061", - "0x4c29547f452fd736598991b8bb296e53e86caa5c3c4364ecfeea305bb7b22fd0": "0x0000000000000000000000007a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x6736ab4999a73108ab8ac21ffd41cc04433a97cf07b814c9219acbf870701a70": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "0x0000000000000000000000007a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82": "0x0000000000000000000000007a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x8c408ba05a2c1c38f8f835492b4e7a17c1a4979a24a23659ed0847b181afa169": "0x0000000000000000000000007a2b5390bb632269133d3b7eda466b4b44bf2762", + "0x800ab95231c8300368c5183ff4f29b54267dc887ff4bdba9a3c7d261e8e23357": "0x0000000000000000000000000000000000000000000000000000000000000061", + "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "0x00000000000000000000000045dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82": "0x00000000000000000000000045dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x882fcd6ad65d6b881b736e03202e72aa4820efbf85e957a2eefa1db99e6b0bf7": "0x00000000000000000000000045dfd9f6da52abaee54ad49226c698e45b2f3777", "0x92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x9fd22f50db652b5a02069e1e70a1d4e05cfa705ac6dce344b87e5aec62c902bf": "0x0000000000000000000000007a2b5390bb632269133d3b7eda466b4b44bf2762", - "0xa744f52b287c3e302328427e079fff658bea984284c892e1cedca11e3fd3bf76": "0x0000000000000000000000000000000000000000000000000000000000000001" + "0x989e0935e5eb704164e806605aa7236ab3b0491c1532892656ca9146005605bf": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9d70ac842bcd0aa6584820c5c41e2ff619d598e37cf249fbc4e4d23d6aa86d5d": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xab96d7f7ff423c5cf59be6a79eba33259c631859a01085a9a08ff1952f4c7b61": "0x00000000000000000000000045dfd9f6da52abaee54ad49226c698e45b2f3777", + "0xeca75a8ba86c40655ff183321d57ce0e05e5140e90ba59f0e7aec436354ee04b": "0x0000000000000000000000000000000000000000000000000000000000000001" }, "balance": "0x0" }, @@ -189,16 +183,8 @@ "0000000000000000000000000000000000001004": { "code": "0x608060405234801561001057600080fd5b50600436106103e65760003560e01c8063820706e41161020a578063b7bb66d211610125578063d6491c55116100b8578063e1b526b011610087578063e1b526b014610a15578063e860cb8f14610a28578063eb1133ee14610a30578063fe575a8714610a57578063feac729d14610a6a57600080fd5b8063d6491c551461099f578063deaa406e146109c6578063e0a8f6f5146109ef578063e0fccde814610a0257600080fd5b8063c7f758a8116100f4578063c7f758a814610946578063c8541fe014610966578063ce236ec414610979578063cf44550e1461098c57600080fd5b8063b7bb66d2146108dd578063bfbd7f4c146108e5578063bfdddcc2146108f8578063c1b66bf21461091f57600080fd5b806398951b561161019d578063a6c96cad1161016c578063a6c96cad1461087b578063a96b3a92146108a2578063affe1400146108c2578063b20ccd16146108ca57600080fd5b806398951b561461081b5780639d4973661461082e578063a11f9caa14610841578063a67bdb911461086857600080fd5b806385752d03116101d957806385752d03146107bb578063911ad022146107ce57806393a8bb99146107e157806394d11082146107f457600080fd5b8063820706e414610761578063824ea8ed146107745780638465fc631461079557806384fd5477146107a857600080fd5b80635216de37116103055780636a6debd71161029857806377989bac1161026757806377989bac146106e45780637a1d67341461070b5780637c5a43ec146107325780637f4b33e9146107455780637f5d6dcc1461074e57600080fd5b80636a6debd71461069c5780636ad89315146106a457806373098faf146106ad578063774c9ce2146106dc57600080fd5b806363869328116102d4578063638693281461064557806363bc2f441461065a5780636525741014610681578063657ceef61461069457600080fd5b80635216de37146105e55780635c646aa6146105f85780635ce9284f1461060b5780636079a85a1461061e57600080fd5b80631c189d181161037d578063291795f91161034c578063291795f9146105785780632d6e57151461059f5780633bcb5a7d146105bf5780633d4c0452146105d257600080fd5b80631c189d181461050057806320a302681461051357806323e890961461053e57806324b858c81461056557600080fd5b80630d61b519116103b95780630d61b5191461048f5780630e12ebd7146104b2578063132e578b146104bb5780631703a018146104db57600080fd5b8063011f78c0146103eb578063013cf08b1461040657806308ae4b0c146104305780630d3212731461047c575b600080fd5b6103f3600381565b6040519081526020015b60405180910390f35b6104196104143660046149fe565b610a73565b6040516103fd9b9a99989796959493929190614a99565b61046061043e366004614b31565b60056020526000908152604090205460ff811690610100900463ffffffff1682565b60408051921515835263ffffffff9091166020830152016103fd565b6103f361048a366004614b31565b610b75565b6104a261049d3660046149fe565b610c4e565b60405190151581526020016103fd565b6103f3600c5481565b6103f36104c93660046149fe565b600a6020526000908152604090205481565b6004546104eb9063ffffffff1681565b60405163ffffffff90911681526020016103fd565b6104a261050e366004614b4e565b610c65565b610526610521366004614b7a565b610ce5565b6040516001600160a01b0390911681526020016103fd565b6103f37f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b81565b6104a26105733660046149fe565b610d54565b6103f37fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d81565b6105b26105ad366004614b7a565b610d6b565b6040516103fd9190614b9c565b6104a26105cd3660046149fe565b610d80565b6103f36105e0366004614b31565b610f41565b6103f36105f3366004614be9565b610fd9565b6103f3610606366004614c70565b6110b8565b6103f36106193660046149fe565b61125c565b6103f37ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee81565b610658610653366004614b31565b61127e565b005b6103f37f2e7eab62cb105bbcf2673dc7e79b70b7501abec6a6b72746bd2f6057382a472481565b61052661068f366004614b7a565b6114f3565b6103f3600181565b6103f361152b565b6103f360015481565b6104a26106bb366004614b31565b600c546001600160a01b039091166000908152600b60205260409020541090565b6103f360ff81565b6103f37f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a81565b6103f37f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e81565b6104eb6107403660046149fe565b61153b565b6103f360005481565b61052661075c3660046149fe565b611582565b6105b261076f366004614b7a565b61158f565b6107876107823660046149fe565b61159d565b6040516103fd929190614ca9565b6104a26107a33660046149fe565b61165d565b6104a26107b6366004614b31565b61183f565b6104a26107c9366004614b4e565b61197d565b6103f36107dc366004614be9565b6119bd565b6103f36107ef366004614b31565b611a92565b6103f37f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac381565b6106586108293660046149fe565b611b52565b6103f361083c366004614cc7565b611b6c565b6103f37fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb81565b6103f36108763660046149fe565b611c74565b6103f37fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b5881565b6103f36108b0366004614b31565b600b6020526000908152604090205481565b6105b2611d22565b6105266108d83660046149fe565b611d2e565b6105b2611d3b565b6103f36108f3366004614c70565b611d47565b6103f37fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed281565b6103f37fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a081565b6109596109543660046149fe565b611eb8565b6040516103fd9190614ce4565b6106586109743660046149fe565b612081565b6103f3610987366004614be9565b612097565b6103f361099a366004614b31565b6121a0565b6103f37fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b81565b6103f36109d4366004614b31565b6001600160a01b03166000908152600b602052604090205490565b6106586109fd3660046149fe565b612238565b6103f3610a10366004614be9565b612342565b6104a2610a233660046149fe565b61244b565b6103f361251a565b6103f37ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b81565b6104a2610a65366004614b31565b612525565b6103f360025481565b600760208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701549787018054969895979496939592946001600160a01b0383169463ffffffff600160a01b8504811695600160c01b8604821695600160e01b90049091169360ff9091169291610af290614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1e90614da6565b8015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b820191906000526020600020905b815481529060010190602001808311610b4e57829003601f168201915b505050505090508b565b336000908152600560205260408120805460ff16610ba6576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b038316610bcd576040516342bcdf7f60e11b815260040160405180910390fd5b610bd8603284612644565b15610bf657604051632ada027560e21b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b91015b60405160208183030381529060405261267e565b91505b50919050565b600081610c5a816128f3565b610c458360006129af565b6000610c7082612ccd565b6000818152600760205260408120600181015492945091610c92908690612cff565b60018301546000908152600660205260409020549091508110610cba57600092505050610cdf565b60ff811115610cce57600092505050610cdf565b600290910154600190911b16151590505b92915050565b600080610cf184612d53565b60008181526006602052604090208054919250908410610d2457604051634e23d03560e01b815260040160405180910390fd5b808481548110610d3657610d36614dda565b6000918252602090912001546001600160a01b031695945050505050565b600081610d60816128f3565b610c458360016129af565b6060610d7960348484612d81565b9392505050565b60008060076000610d9085612ccd565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff166007811115610e3f57610e3f614a17565b6007811115610e5057610e50614a17565b8152602001600782018054610e6490614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9090614da6565b8015610edd5780601f10610eb257610100808354040283529160200191610edd565b820191906000526020600020905b815481529060010190602001808311610ec057829003601f168201915b505050505081525050905060016007811115610efb57610efb614a17565b8161012001516007811115610f1257610f12614a17565b03610f38576000548160600151610f299190614e06565b4211610f385750600192915050565b50600092915050565b336000908152600560205260408120805460ff16610f72576040516305031d1160e31b815260040160405180910390fd5b610f7d603284612644565b610f9a576040516326a5b9a160e21b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac39101610c31565b336000908152600560205260408120805460ff1661100a576040516305031d1160e31b815260040160405180910390fd5b60005b838110156110765761104785858381811061102a5761102a614dda565b905060200201602081019061103f9190614b31565b603490612644565b611064576040516305da0e2560e11b815260040160405180910390fd5b8061106e81614e1e565b91505061100d565b506110ae7fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b8585604051602001610c31929190614e37565b91505b5092915050565b336000908152600560205260408120805460ff166110e9576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b0384166111105760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff161561114a5760405163a929afd160e01b815260040160405180910390fd5b60015460009081526006602052604090205460ff811061117d5760405163443afd7960e01b815260040160405180910390fd5b600061118a826001614e06565b9050806001036111c0578463ffffffff166001146111bb5760405163d173577960e01b815260040160405180910390fd5b6111f8565b60028563ffffffff1610806111da5750808563ffffffff16115b156111f85760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff87168183015281518082038301815260609091019091526112517fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb8261267e565b979650505050505050565b60008061126883612d53565b6000908152600660205260409020549392505050565b336000908152600560205260409020805460ff166112af576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b0383166112d75760405163ddf1d6dd60e01b815260040160405180910390fd5b826001600160a01b0316816001600160a01b0316036113095760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03831660009081526005602052604090205460ff16156113435760405163a929afd160e01b815260040160405180910390fd5b600154600081815260066020526040812080549091805b8281101561142e57856001600160a01b031684828154811061137e5761137e614dda565b6000918252602090912001546001600160a01b03160361141c57878482815481106113ab576113ab614dda565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790558782526008815260408083208a851680855292528083208054948d168452908320805463ffffffff90951663ffffffff199586161790559152805490911690556001915061142e565b8061142681614e1e565b91505061135a565b508061144d576040516305031d1160e31b815260040160405180910390fd5b604080518082018252600181524263ffffffff90811660208084019182526001600160a01b038c81166000818152600590935286832095518654945164ffffffffff1990951690151564ffffffff00191617610100949095169390930293909317909355908816808352838320805460ff1916905592519092917f05d866cd9c6000815d031b7ce30f30f643766eba16be13cff25924dc8ad8209291a350505050505050565b6006602052816000526040600020818154811061150f57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600061153660345490565b905090565b60008061154783612d53565b60008181526009602052604081205491925063ffffffff90911690819003610d795760405163d173577960e01b815260040160405180910390fd5b6000610cdf603483612eae565b6060610d7960328484612d81565b6000808215806115ae575060025483115b156115bf5750600192600092509050565b60008381526007602052604090206002600682015460ff1660078111156115e8576115e8614a17565b146115fa575060029360009350915050565b600054816003015461160c9190614e06565b421115611620575060039360009350915050565b6000848152600a60205260409020546003811061164557506004946000945092505050565b6000611652826003614e85565b935093505050915091565b6000806007600061166d85612ccd565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff16600781111561171c5761171c614a17565b600781111561172d5761172d614a17565b815260200160078201805461174190614da6565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90614da6565b80156117ba5780601f1061178f576101008083540402835291602001916117ba565b820191906000526020600020905b81548152906001019060200180831161179d57829003601f168201915b5050505050815250509050600260078111156117d8576117d8614a17565b81610120015160078111156117ef576117ef614a17565b146117fd5750600092915050565b600054816060015161180f9190614e06565b42111561181f5750600092915050565b8060c0015163ffffffff168160e0015163ffffffff161015915050919050565b60006001600160a01b038216611868576040516342bcdf7f60e11b815260040160405180910390fd5b6036546040516001600160a01b038481166024830152600092839291169060440160408051601f198184030181529181526020820180516001600160e01b03166301fd3f7760e71b179052516118be9190614e9c565b600060405180830381855afa9150503d80600081146118f9576040519150601f19603f3d011682016040523d82523d6000602084013e6118fe565b606091505b5091509150816119615760405162461bcd60e51b8152602060048201526024808201527f476f76436f756e63696c3a206973417574686f72697a65642063616c6c2066616044820152631a5b195960e21b60648201526084015b60405180910390fd5b808060200190518101906119759190614eb8565b949350505050565b60008061198983612d53565b60009081526008602090815260408083206001600160a01b038816845290915290205463ffffffff16151591505092915050565b336000908152600560205260408120805460ff166119ee576040516305031d1160e31b815260040160405180910390fd5b60005b83811015611a5a57611a2b858583818110611a0e57611a0e614dda565b9050602002016020810190611a239190614b31565b603290612644565b611a48576040516326a5b9a160e21b815260040160405180910390fd5b80611a5281614e1e565b9150506119f1565b506110ae7fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed28585604051602001610c31929190614e37565b336000908152600560205260408120805460ff16611ac3576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b038316611aea576040516342bcdf7f60e11b815260040160405180910390fd5b611af5603484612644565b15611b13576040516301f0c0eb60e11b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee9101610c31565b80611b5c816128f3565b611b6882600180612f03565b5050565b336000908152600560205260408120805460ff16611b9d576040516305031d1160e31b815260040160405180910390fd5b6001805460009081526006602052604090205490819003611be4578363ffffffff16600114611bdf5760405163d173577960e01b815260040160405180910390fd5b611c1c565b60028463ffffffff161080611bfe5750808463ffffffff16115b15611c1c5760405163d173577960e01b815260040160405180910390fd5b6040805163ffffffff86166020820152600091016040516020818303038152906040529050611c6b7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b8261267e565b95945050505050565b336000908152600560205260408120805460ff16611ca5576040516305031d1160e31b815260040160405180910390fd5b6001831080611cb45750603283115b15611cd25760405163e46113f560e01b815260040160405180910390fd5b600083604051602001611ce791815260200190565b60405160208183030381529060405290506119757fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b588261267e565b6060611536603261331f565b6000610cdf603283612eae565b6060611536603461331f565b336000908152600560205260408120805460ff16611d78576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff16611db1576040516305031d1160e31b815260040160405180910390fd5b60018054600090815260066020526040902054908111611de45760405163d173577960e01b815260040160405180910390fd5b6000611df1600183614e85565b905080600103611e27578463ffffffff16600114611e225760405163d173577960e01b815260040160405180910390fd5b611e5f565b60028563ffffffff161080611e415750808563ffffffff16115b15611e5f5760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff87168183015281518082038301815260609091019091526112517fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d8261267e565b611f176040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052906101208201908152602001606081525090565b611f2082612ccd565b60008181526007602081815260409283902083516101608101855281548152600182015492810192909252600281015493820193909352600383015460608201526004830154608082015260058301546001600160a01b03811660a083015263ffffffff600160a01b8204811660c0840152600160c01b8204811660e0840152600160e01b9091041661010082015260068301549395509261012084019160ff90911690811115611fd357611fd3614a17565b6007811115611fe457611fe4614a17565b8152602001600782018054611ff890614da6565b80601f016020809104026020016040519081016040528092919081815260200182805461202490614da6565b80156120715780601f1061204657610100808354040283529160200191612071565b820191906000526020600020905b81548152906001019060200180831161205457829003601f168201915b5050505050815250509050919050565b8061208b816128f3565b611b6882600080612f03565b336000908152600560205260408120805460ff166120c8576040516305031d1160e31b815260040160405180910390fd5b60005b838110156121685760008585838181106120e7576120e7614dda565b90506020020160208101906120fc9190614b31565b6001600160a01b031603612123576040516342bcdf7f60e11b815260040160405180910390fd5b612138858583818110611a0e57611a0e614dda565b1561215657604051632ada027560e21b815260040160405180910390fd5b8061216081614e1e565b9150506120cb565b506110ae7fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a08585604051602001610c31929190614e37565b336000908152600560205260408120805460ff166121d1576040516305031d1160e31b815260040160405180910390fd5b6121dc603484612644565b6121f9576040516305da0e2560e11b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e9101610c31565b80612242816128f3565b60008281526007602052604090206001600682015460ff16600781111561226b5761226b614a17565b14612289576040516377036cbb60e01b815260040160405180910390fd5b60058101546001600160a01b031633146122b657604051637d1b73b960e01b815260040160405180910390fd5b60058101546001600160c01b90910463ffffffff1611806122e757506005810154600160e01b900463ffffffff1615155b15612305576040516355fe710960e01b815260040160405180910390fd5b612310836004613385565b604051339084907f74c34a008ce735d9fcf0bd03a9b238d212ad4c441c020661f4ffbb6442645b8590600090a3505050565b336000908152600560205260408120805460ff16612373576040516305031d1160e31b815260040160405180910390fd5b60005b8381101561241357600085858381811061239257612392614dda565b90506020020160208101906123a79190614b31565b6001600160a01b0316036123ce576040516342bcdf7f60e11b815260040160405180910390fd5b6123e385858381811061102a5761102a614dda565b15612401576040516301f0c0eb60e11b815260040160405180910390fd5b8061240b81614e1e565b915050612376565b506110ae7f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a8585604051602001610c31929190614e37565b600081612457816128f3565b60008381526007602052604090206001600682015460ff16600781111561248057612480614a17565b141580156124a757506002600682015460ff1660078111156124a4576124a4614a17565b14155b156124b6576000925050610c48565b60005481600301546124c89190614e06565b42116124d8576000925050610c48565b6124e3846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a35060019392505050565b600061153660325490565b60006001600160a01b03821661254e576040516342bcdf7f60e11b815260040160405180910390fd5b6036546040516001600160a01b038481166024830152600092839291169060440160408051601f198184030181529181526020820180516001600160e01b031663fe575a8760e01b179052516125a49190614e9c565b600060405180830381855afa9150503d80600081146125df576040519150601f19603f3d011682016040523d82523d6000602084013e6125e4565b606091505b5091509150816119615760405162461bcd60e51b815260206004820152602560248201527f476f76436f756e63696c3a206973426c61636b6c69737465642063616c6c2066604482015264185a5b195960da1b6064820152608401611958565b60006001600160a01b03821661265c57506000610cdf565b506001600160a01b031660009081526001919091016020526040902054151590565b336000908152600560205260408120805460ff166126af576040516305031d1160e31b815260040160405180910390fd5b6000546000036126d2576040516387321fdd60e01b815260040160405180910390fd5b600c54336000908152600b6020526040902054106127035760405163090b564b60e01b815260040160405180910390fd5b60026000815461271290614e1e565b918290555060408051610160810182528681526001805460208301526000928201839052426060830152608082018390523360a083015260045463ffffffff1660c083015260e0820183905261010082019290925291935061012082019081526020908101859052600084815260078083526040918290208451815592840151600180850191909155918401516002840155606084015160038401556080840151600484015560a084015160058401805460c087015160e08801516101008901516001600160a01b039095166001600160c01b031990931692909217600160a01b63ffffffff92831602176001600160c01b0316600160c01b928216929092026001600160e01b031691909117600160e01b91909316029190911790556101208401516006840180549193909260ff1990921691849081111561285757612857614a17565b0217905550610140820151805161287891600784019160209091019061496e565b505060015460045460405133935085927f830652010a654c24b39890c16f53e6f6179becc61702ecd9a8c88461c2ff941a926128bf928a929163ffffffff16908a90614eda565b60405180910390a3336000908152600b602052604081208054916128e283614e1e565b91905055506110b182600180612f03565b60006007600061290284612ccd565b815260200190815260200160002090506000612922338360010154612cff565b60018301546000908152600660205260409020805491925090821061295a576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b031681838154811061297657612976614dda565b6000918252602090912001546001600160a01b0316146129a9576040516305031d1160e31b815260040160405180910390fd5b50505050565b60006129b96133f5565b8215806129c7575060025483115b156129e557604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206002600682015460ff166007811115612a0e57612a0e614a17565b14612a2c57604051633c7e994560e11b815260040160405180910390fd5b600581015463ffffffff600160a01b82048116600160c01b909204161015612a6757604051638af69cf160e01b815260040160405180910390fd5b6000548160030154612a799190614e06565b421115612ac257612a8b846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a36000915050612cc3565b6000848152600a6020526040902054600311612b5957612ae3846006613385565b604080518082018252601781527f4d617820726574727920636f756e74207265616368656400000000000000000060208201529051339186917f68d5d5ea31f430b04112f5edc367c01af04da56d10cd663fbfbc4fbe5f509c2091612b4791614f0f565b60405180910390a36000915050612cc3565b6000848152600a60205260408120805491612b7383614e1e565b9190505550612c128160000154826007018054612b8f90614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054612bbb90614da6565b8015612c085780601f10612bdd57610100808354040283529160200191612c08565b820191906000526020600020905b815481529060010190602001808311612beb57829003601f168201915b505050505061341f565b91508115612c6257612c25846003613385565b60405160018152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a3612cc1565b8215612c7857612c73846006613385565b612c88565b60068101805460ff191660021790555b60405160008152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a35b505b610cdf6000600355565b6000811580612cdd575060025482115b15612cfb57604051631dc0650160e31b815260040160405180910390fd5b5090565b60008181526008602090815260408083206001600160a01b038616845290915281205463ffffffff16808203612d3a57600019915050610cdf565b612d45600182614f22565b63ffffffff16949350505050565b6000811580612d63575060015482115b15612cfb576040516315ed869560e21b815260040160405180910390fd5b606082821015612da457604051634e23d03560e01b815260040160405180910390fd5b8354808310612dc657604051634e23d03560e01b815260040160405180910390fd5b6000612dd28585614e85565b612ddd906001614e06565b90508067ffffffffffffffff811115612df857612df8614f47565b604051908082528060200260200182016040528015612e21578160200160208202803683370190505b50925060005b81811015612ea45786612e3a8288614e06565b81548110612e4a57612e4a614dda565b9060005260206000200160009054906101000a90046001600160a01b0316848281518110612e7a57612e7a614dda565b6001600160a01b039092166020928302919091019091015280612e9c81614e1e565b915050612e27565b5050509392505050565b81546000908210612ed257604051634e23d03560e01b815260040160405180910390fd5b826000018281548110612ee757612ee7614dda565b6000918252602090912001546001600160a01b03169392505050565b821580612f11575060025483115b15612f2f57604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206001600682015460ff166007811115612f5857612f58614a17565b14158015612f7f57506002600682015460ff166007811115612f7c57612f7c614a17565b14155b15612f9d576040516377036cbb60e01b815260040160405180910390fd5b6000548160030154612faf9190614e06565b421115612ff457612fc1846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a350505050565b600181015460006130053383612cff565b60008381526006602052604090208054919250908210613038576040516305031d1160e31b815260040160405180910390fd5b60ff82111561305a5760405163443afd7960e01b815260040160405180910390fd5b60028401546001831b908116156130845760405163080fc0bd60e11b815260040160405180910390fd5b6002850180548217905586156131e65760058501546000906130b490600160c01b900463ffffffff166001614f5d565b60058701805463ffffffff60c01b1916600160c01b63ffffffff848116918202929092179283905560408051600181526020810192909252600160e01b90930490911681830152905191925033918b917f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc05919081900360600190a3600586015463ffffffff600160a01b9091048116908216106131e0576002600687015460ff16600781111561316657613166614a17565b146131cd5760068601805460ff1916600217905560058601546040805163ffffffff8481168252600160e01b909304909216602083015233918b917f5064fb9bf50f615c47cc24c49119ba31d2c1a83ad6aed3b226cd42005524b7f4910160405180910390a35b86156131e0576131de8960006129af565b505b50613315565b600585015460009061320690600160e01b900463ffffffff166001614f5d565b6005870180546001600160e01b0316600160e01b63ffffffff84811691820292909217928390556040805160008152600160c01b90940490921660208401529082015290915033908a907f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc059060600160405180910390a36005860154835460009161329f91600160a01b90910463ffffffff1690614f22565b90508063ffffffff168263ffffffff161115613312576132c08a6007613385565b60058701546040805163ffffffff600160c01b90930483168152918416602083015233918c917f6fa60fd92b2557298bb7b39e7b538b3f00ebf09b9f056bdeac7f0e5d57e8fcbb910160405180910390a35b50505b5050505050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561337957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161335b575b50505050509050919050565b60008281526007602081905260409091206006018054839260ff199091169060019084908111156133b8576133b8614a17565b021790555060038160078111156133d1576133d1614a17565b036133ec576000828152600760205260409020426004909101555b611b6882613568565b600354600103613418576040516306fda65d60e31b815260040160405180910390fd5b6001600355565b60007fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb8303613478576000808380602001905181019061345f9190614f85565b9150915061346d82826135c7565b600192505050610cdf565b7fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d83036134c457600080838060200190518101906134b69190614f85565b9150915061346d828261390f565b7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b8303613516576000828060200190518101906135019190614fb4565b905061350c81613bc7565b6001915050610cdf565b7fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b58830361355e576000828060200190518101906135539190614fd1565b905061350c81613cca565b610d798383613d3c565b6000818152600760209081526040808320600501546001600160a01b0316808452600b9092529091205415611b68576001600160a01b0381166000908152600b602052604081208054916135bb83614fea565b91905055505050565b50565b6001600160a01b03821660009081526005602052604090205460ff16156136015760405163a929afd160e01b815260040160405180910390fd5b6001600160a01b0382166136285760405163ddf1d6dd60e01b815260040160405180910390fd5b6000806000613635614089565b81549295509093509150600061364c826001614e06565b905060ff821061366f5760405163443afd7960e01b815260040160405180910390fd5b806001036136a3578563ffffffff1660011461369e5760405163d173577960e01b815260040160405180910390fd5b6136db565b60028663ffffffff1610806136bd5750808663ffffffff16115b156136db5760405163d173577960e01b815260040160405180910390fd5b60005b828110156137945760008582815481106136fa576136fa614dda565b6000918252602080832090910154895460018181018c558b85529290932090920180546001600160a01b0319166001600160a01b039093169283179055909150613745908390614e06565b60008681526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff9092169190911790558061378c81614e1e565b9150506136de565b5084546001808201875560008781526020902090910180546001600160a01b0319166001600160a01b038a161790556137ce908390614e06565b60008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff1990811663ffffffff978816179091558251808401845260018152428716818601908152838752600586529584902090518154965164ffffffffff1990971690151564ffffffff001916176101009688169690960295909517909455600480549485168c87169081179091558a5483519081529384015292909316927fd693483bf3059d721fcb091390377153e45c1b15c85015ea8c5547b92960ff56910160405180910390a26040805163ffffffff8084168252891660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a15050506000908152600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b6001600160a01b03821660009081526005602052604090205460ff16613948576040516305031d1160e31b815260040160405180910390fd5b6000806000613955614089565b81549295509093509150600061396c600183614e85565b90508060000361398f5760405163d173577960e01b815260040160405180910390fd5b806001036139c3578563ffffffff166001146139be5760405163d173577960e01b815260040160405180910390fd5b6139fb565b60028663ffffffff1610806139dd5750808663ffffffff16115b156139fb5760405163d173577960e01b815260040160405180910390fd5b6000805b83811015613ac4576000868281548110613a1b57613a1b614dda565b6000918252602090912001546001600160a01b0390811691508a168103613a425750613ab2565b87546001810189556000898152602090200180546001600160a01b0319166001600160a01b038316179055613a7683614e1e565b60008781526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff831617905591505b80613abc81614e1e565b9150506139ff565b5060008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff199081169091556005845293829020805460ff191690556004805494851663ffffffff8d81169182179092558b5484519081529485015290931692917fab15a70783712986077aea9a4cbfd4c1561dd8672489037c581fbaf8fc658516910160405180910390a26040805163ffffffff80841682528a1660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a1505050600091825250600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b6001805460009081526006602052604090205490819003613c0e578163ffffffff16600114613c095760405163d173577960e01b815260040160405180910390fd5b613c46565b60028263ffffffff161080613c285750808263ffffffff16115b15613c465760405163d173577960e01b815260040160405180910390fd5b6004805463ffffffff84811663ffffffff1983168117909355604080519190921680825260208201939093527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a150506001546000908152600960205260409020805463ffffffff191663ffffffff92909216919091179055565b6001811080613cd95750603281115b15613cf75760405163e46113f560e01b815260040160405180910390fd5b600c80549082905560408051828152602081018490527f56b9de3a8fc94721b6e3f917d89308667325aefa7d3d6d99b42acda37f3855bf910160405180910390a15050565b60007f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b8303613d9157600082806020019051810190613d7b9190615001565b9050613d89816002546140c4565b915050610cdf565b7fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a08303613e1f57600082806020019051810190613dce919061502e565b905060005b8151811015613e1457613e01828281518110613df157613df1614dda565b60200260200101516002546140c4565b5080613e0c81614e1e565b915050613dd3565b506001915050610cdf565b7f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac38303613e6a57600082806020019051810190613e5c9190615001565b9050613d8981600254614292565b7fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed28303613eed57600082806020019051810190613ea7919061502e565b905060005b8151811015613e1457613eda828281518110613eca57613eca614dda565b6020026020010151600254614292565b5080613ee581614e1e565b915050613eac565b7ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee8303613f3857600082806020019051810190613f2a9190615001565b9050613d898160025461443c565b7f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a8303613fbb57600082806020019051810190613f75919061502e565b905060005b8151811015613e1457613fa8828281518110613f9857613f98614dda565b602002602001015160025461443c565b5080613fb381614e1e565b915050613f7a565b7f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e830361400657600082806020019051810190613ff89190615001565b9050613d89816002546145e7565b7fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b8303610f3857600082806020019051810190614043919061502e565b905060005b8151811015613e145761407682828151811061406657614066614dda565b60200260200101516002546145e7565b508061408181614e1e565b915050614048565b60008060008060015490508060016140a19190614e06565b600091825260066020526040808320828452922060018290559591945092509050565b60006140d1603284612644565b156141345781836001600160a01b031660008051602061510a833981519152604051614124906020808252601390820152721053149150511657d0931050d2d31254d51151606a1b604082015260600190565b60405180910390a3506000610cdf565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316633e7e4af960e21b179052516141879190614e9c565b6000604051808303816000865af19150503d80600081146141c4576040519150601f19603f3d011682016040523d82523d6000602084013e6141c9565b606091505b50509050806142465782846001600160a01b031660008051602061510a8339815191526040516142349060208082526021908201527f476f76436f756e63696c3a20626c61636b6c6973742063616c6c206661696c656040820152601960fa1b606082015260800190565b60405180910390a36000915050610cdf565b61425160328561478f565b5060405183906001600160a01b038616907f1d2c7e6b911a4ad6c07d780ccd7e533749bff42c2b1d161c21f3fc7c830eb2cc90600090a35060019392505050565b600061429f603284612644565b6142ee5781836001600160a01b031660008051602061510a8339815191526040516141249060208082526010908201526f1393d517d25397d0931050d2d31254d560821b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316630d44a93360e11b179052516143419190614e9c565b6000604051808303816000865af19150503d806000811461437e576040519150601f19603f3d011682016040523d82523d6000602084013e614383565b606091505b50509050806143f05782846001600160a01b031660008051602061510a8339815191526040516142349060208082526023908201527f476f76436f756e63696c3a20756e426c61636b6c6973742063616c6c206661696040820152621b195960ea1b606082015260800190565b6143fb603285614828565b5060405183906001600160a01b038616907f5428c9b1fb7549fe41c6846061bfb4c682760e630052c3d880669ece73427cb790600090a35060019392505050565b6000614449603484612644565b1561449b5781836001600160a01b031660008051602061510a833981519152604051614124906020808252601290820152711053149150511657d055551213d49256915160721b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316635b52ebef60e11b179052516144ee9190614e9c565b6000604051808303816000865af19150503d806000811461452b576040519150601f19603f3d011682016040523d82523d6000602084013e614530565b606091505b505090508061459b5782846001600160a01b031660008051602061510a8339815191526040516142349060208082526021908201527f476f76436f756e63696c3a20617574686f72697a652063616c6c206661696c656040820152601960fa1b606082015260800190565b6145a660348561478f565b5060405183906001600160a01b038616907f3110d1ee06428a72c2523738b03b74d2cac172112945536944ef0d34f917594790600090a35060019392505050565b60006145f4603484612644565b6146415781836001600160a01b031660008051602061510a833981519152604051614124906020808252600e908201526d1393d517d055551213d49256915160921b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316633bbbc7c960e01b179052516146949190614e9c565b6000604051808303816000865af19150503d80600081146146d1576040519150601f19603f3d011682016040523d82523d6000602084013e6146d6565b606091505b50509050806147435782846001600160a01b031660008051602061510a8339815191526040516142349060208082526023908201527f476f76436f756e63696c3a20756e417574686f72697a652063616c6c206661696040820152621b195960ea1b606082015260800190565b61474e603485614828565b5060405183906001600160a01b038616907f50481a3a74ecdf57138218d3d03198c96d338a47f85893e68628c4689d71534790600090a35060019392505050565b60006001600160a01b0382166147b8576040516342bcdf7f60e11b815260040160405180910390fd5b6147c28383612644565b156147e05760405163516c350f60e11b815260040160405180910390fd5b508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03959095169485179055845493815293810190915260409092205590565b6001600160a01b038116600090815260018301602052604081205480820361486357604051636054b46960e01b815260040160405180910390fd5b6000614870600183614e85565b855490915060009061488490600190614e85565b90508082146149105760008660000182815481106148a4576148a4614dda565b60009182526020909120015487546001600160a01b03909116915081908890859081106148d3576148d3614dda565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815260018801909152604090208390555b8554869080614921576149216150f3565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825260018881019091526040822091909155935050505092915050565b82805461497a90614da6565b90600052602060002090601f01602090048101928261499c57600085556149e2565b82601f106149b557805160ff19168380011785556149e2565b828001600101855582156149e2579182015b828111156149e25782518255916020019190600101906149c7565b50612cfb9291505b80821115612cfb57600081556001016149ea565b600060208284031215614a1057600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60088110614a3d57614a3d614a17565b9052565b60005b83811015614a5c578181015183820152602001614a44565b838111156129a95750506000910152565b60008151808452614a85816020860160208601614a41565b601f01601f19169290920160200192915050565b8b8152602081018b9052604081018a905260608101899052608081018890526001600160a01b03871660a082015263ffffffff86811660c083015285811660e083015284166101008201526000610160614af7610120840186614a2d565b80610140840152614b0a81840185614a6d565b9e9d5050505050505050505050505050565b6001600160a01b03811681146135c457600080fd5b600060208284031215614b4357600080fd5b8135610d7981614b1c565b60008060408385031215614b6157600080fd5b8235614b6c81614b1c565b946020939093013593505050565b60008060408385031215614b8d57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015614bdd5783516001600160a01b031683529284019291840191600101614bb8565b50909695505050505050565b60008060208385031215614bfc57600080fd5b823567ffffffffffffffff80821115614c1457600080fd5b818501915085601f830112614c2857600080fd5b813581811115614c3757600080fd5b8660208260051b8501011115614c4c57600080fd5b60209290920196919550909350505050565b63ffffffff811681146135c457600080fd5b60008060408385031215614c8357600080fd5b8235614c8e81614b1c565b91506020830135614c9e81614c5e565b809150509250929050565b6040810160058410614cbd57614cbd614a17565b9281526020015290565b600060208284031215614cd957600080fd5b8135610d7981614c5e565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a0830151614d3360c08401826001600160a01b03169052565b5060c083015163ffffffff811660e08401525060e0830151610100614d5f8185018363ffffffff169052565b8401519050610120614d788482018363ffffffff169052565b8401519050610140614d8c84820183614a2d565b8401516101608481015290506110ae610180840182614a6d565b600181811c90821680614dba57607f821691505b602082108103610c4857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115614e1957614e19614df0565b500190565b600060018201614e3057614e30614df0565b5060010190565b60208082528181018390526000908460408401835b86811015614e7a578235614e5f81614b1c565b6001600160a01b031682529183019190830190600101614e4c565b509695505050505050565b600082821015614e9757614e97614df0565b500390565b60008251614eae818460208701614a41565b9190910192915050565b600060208284031215614eca57600080fd5b81518015158114610d7957600080fd5b84815283602082015263ffffffff83166040820152608060608201526000614f056080830184614a6d565b9695505050505050565b602081526000610d796020830184614a6d565b600063ffffffff83811690831681811015614f3f57614f3f614df0565b039392505050565b634e487b7160e01b600052604160045260246000fd5b600063ffffffff808316818516808303821115614f7c57614f7c614df0565b01949350505050565b60008060408385031215614f9857600080fd5b8251614fa381614b1c565b6020840151909250614c9e81614c5e565b600060208284031215614fc657600080fd5b8151610d7981614c5e565b600060208284031215614fe357600080fd5b5051919050565b600081614ff957614ff9614df0565b506000190190565b60006020828403121561501357600080fd5b8151610d7981614b1c565b805161502981614b1c565b919050565b6000602080838503121561504157600080fd5b825167ffffffffffffffff8082111561505957600080fd5b818501915085601f83011261506d57600080fd5b81518181111561507f5761507f614f47565b8060051b604051601f19603f830116810181811085821117156150a4576150a4614f47565b6040529182528482019250838101850191888311156150c257600080fd5b938501935b828510156150e7576150d88561501e565b845293850193928501926150c7565b98975050505050505050565b634e487b7160e01b600052603160045260246000fdfe5ec90e8f4a61404dd1a1a05fdde3f3ce998aaaf78e579739308751e16300734ea2646970667358221220c9ab53da82cc7ef5444ec14b756ade7ca555d020df1fab2620cf0055fd893ae464736f6c634300080e0033", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001", "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000003", - "0x0000000000000000000000000000000000000000000000000000000000000036": "0x0000000000000000000000000000000000000000000000000000000000b00003", - "0x3133b9fb7810b2a7f735819914587f60831e339d00b86c5bf810f9f39090fd99": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x51dc2ffa66476bb8bdfa05ea53597330d344ad85930a2281ddb9910f878716a1": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "0x000000000000000000000000aa5faa65e9cc0f74a85b6fdfb5f6991f5c094697", - "0x92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36": "0x0000000000000000000000000000000000000000000000000000000000000001" + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x0000000000000000000000000000000000000000000000000000000000b00003" }, "balance": "0x0" }, @@ -230,6 +216,9 @@ "4340ee1b812acb40a1eb561c019c327b243b92df": { "balance": "0xc097ce7bc90715b34b9f1000000000" }, + "45dfd9f6da52abaee54ad49226c698e45b2f3777": { + "balance": "0xc097ce7bc90715b34b9f1000000000" + }, "4a0f1452281bcec5bd90c3dce6162a5995bfe9df": { "balance": "0xc097ce7bc90715b34b9f1000000000" }, @@ -248,9 +237,6 @@ "7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": { "balance": "0xc097ce7bc90715b34b9f1000000000" }, - "7a2b5390bb632269133d3b7eda466b4b44bf2762": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, "7dcd17433742f4c0ca53122ab541d0ba67fc27df": { "code": "0x3680600080376000206000548082558060010160005560005263656d697460206000a2", "balance": "0x0" diff --git a/cmd/devp2p/internal/ethtest/testdata/headblock.json b/cmd/devp2p/internal/ethtest/testdata/headblock.json index 55d7f8b86..44888c704 100644 --- a/cmd/devp2p/internal/ethtest/testdata/headblock.json +++ b/cmd/devp2p/internal/ethtest/testdata/headblock.json @@ -1,23 +1,23 @@ { - "parentHash": "0xa15410b625882ffe13cef2e30e6733c33c24404f770655c327f06276fda3e615", + "parentHash": "0x1acae07cba18f35533545765a20ba0073e105bd754bef5f42ecea25f1a272d3a", "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "miner": "0x7a2b5390bb632269133d3b7eda466b4b44bf2762", - "stateRoot": "0x6c95616f8f988fb794ba25b6027b4643f4cab89f03d19a317a26561bf07392cd", + "miner": "0x45dfd9f6da52abaee54ad49226c698e45b2f3777", + "stateRoot": "0x9f2b9986ee9bcd0a99033304705f7c6f4eb591b2612b6ffb99e6ce7f3882ea58", "transactionsRoot": "0x3872575d14095b63f1ccf5e55b1548ffb68e1175d70cc7d39e8bfb24edbfda92", - "receiptsRoot": "0x71ac7511ee584f8bd35a714fbf557100955ffcc94bec4fd69a3133b6c3888eae", - "logsBloom": "0x00000200002000010000010000000000000000000000000000000004000000900000400000000000000000000000000044000000000000000000000000000000000000000000000000004008400500002000000200000000000100840000000000000420000000020001100000040000000000000000000200040010000000000000000000000000000001801000000000000400000000000000000000000400000000000000000040000000000000000000000000000000000000000000000000008002000000000040000000020000000000000000000000000000000000000000000000000000000001400004001200000000000000000000000000000000", + "receiptsRoot": "0x8cbf43991cfba05f524012a3d1815e02479bf3cc4b634e990a7da7cfb62b2a11", + "logsBloom": "0x00040200002000010000010000000000000000000000000000000004000000900000400000000000000000000800000044000000000000000000000000000000000000000000000000004008400100002000000000000000000100840000000000000420000000020001100000040000000010000000000200040010000000000000000000000000000001801000000000000400000000000000000000000400000000000000000040000000000000000000000000000000000000000000000000008002000000000040000000000000000000000000000000000000000000000000000000000000000001400004001200000000000000000000000000000000", "difficulty": "0x1", "number": "0x1f4", "gasLimit": "0x23f3e20", "gasUsed": "0xfc61", "timestamp": "0x1388", - "extraData": "0xf90252a00000000000000000000000000000000000000000000000000000000000000000b84104146ab708521c17112a712b4841242fd815cea407439ee9921ecd133c7824da4f3e87c915311a82c30225153c8ec9bb24a108fb3bb524d8f4d24205053929180180f86301b860b82c5e057b94ba284bf2e1c72aa1be8bd98a1758003bbb5a13f998917da913d39f0cceabef42d7017c282bcabd47a52110a7cd965931eaf250774e244810a92301b7030601022e3f657619bb9167cbe9719e63298ee4a07f1be6208e5d3fa662f86301b860a9c92e8e6b63384301858395e2af6a6c4b0bee2ab8735afe57327fd6f2252aef74c59b1e2604f08941423515bf617e40003fc0c9374f6fc5799ec94026689bcc51eec82e8c2d6cf651df32b0f7115bf086b91bb680aed31d4fcc55ab5b16d2cc80f86301b860b9a95dbfb04976e9f428199a6b1f54ffaa8cc07e2037952a8e4296172ee6ad7955c903207a26d610cef47fe7ecd940ea0584dbcf58846d7d423d438297b8d3bb483cec136c6efac66a1b6f2a9e6fb714bf21e262093f4f6e07b7c65c661f6502f86301b860a2a281fdbd6b753ad3d7ffdf23981e74d47fb31e938a6bcce354ba5e3d8ab5682432f0eff767ff0b0ec6e12b42a44c961672f63f1151900e4e588a448352cb01eac18d5534343f576133dfda5d94e1a5a885a38723a53a1c64e80448ca9ce4d186048c27395000f84fdad9947a2b5390bb632269133d3b7eda466b4b44bf2762831e8272c180f1b097c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558ef7087a0785870202c45dd49c5de147b3", - "mixHash": "0x1abd716350517c438bc1671a73af2e285baabea8541ced8f0ed9eeb8fd31dccb", + "extraData": "0xf90252a00000000000000000000000000000000000000000000000000000000000000000b841c03c0aeae78257456db9b1a33f953fd10edd9ec061496eeaf6adb1cd43954f527f7a984ebdec5049422044ae77f5033d869a84d442b076e072c14be8eec6f6ff0180f86301b8608c8ef357caafeac2003cead9edaad94202761a87bd2edffce3261e0396176f9559dd02a71887061d354af0220a4c1a460cc3926eab2be9ed38995a66e549db154ad27a2772c1fa17a5f826685831c7e14a8e1a884acf24c47e25a652431c4357f86301b86097810d10d423f3c8f067b48082cd19aa92708d85eed96a500ac14211b32bbd92ebfd5d0ea31ae60c687f20174e7eb31f0282bf22bde1600c056717b2bf861839185ba7df560d7ff9429a0abf0a79f8d30b198d1e05636a02e78520acf09f1f6880f86301b860957faca68736bf2e6270d3b9b223c56eea95c14b46d53540d5b7c789f903d70aad20a0597bd556daabf8dfb663aad6570b0f01a4ff0e6ea5da31efdeff9015cd9d893d67b26ee326e30476fb6bcc7f8c6574e812b8e0aa21fea50603c5b35479f86301b860adc8900c57e770c6215bf79378dec5db7c688cdc6f66bd68f05a9c6d173a635184663018485bac99d4092c69d7f894020d54e5f09bfb9e00d43d1fc12c620ffdd5215f69eb2980eccda1307b6e2a7d423394cdc754283932d5320d5ecfba5f8c86048c27395000f84fdad99445dfd9f6da52abaee54ad49226c698e45b2f3777831e8272c180f1b092272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261fbfc5578c46407b94ba8dcdf6f8c926b", + "mixHash": "0x00f2edc2326d5ba58a90a3418bfc9c4dc8f0da3fb462fdc2ae67411a2820d390", "nonce": "0x0000000000000000", "baseFeePerGas": "0x48c27395000", "withdrawalsRoot": null, "blobGasUsed": null, "excessBlobGas": null, "parentBeaconBlockRoot": null, - "hash": "0x5963f533df1abbcf81b0e74089902c77112c129855f09a26dbd15e5d034dbf61" + "hash": "0x6cbff26011501e62103a791266876e8af1a5399b7b9aaa37de3abe2a9e56d2de" } \ No newline at end of file diff --git a/cmd/devp2p/internal/ethtest/testdata/headfcu.json b/cmd/devp2p/internal/ethtest/testdata/headfcu.json index 9c0d49859..1cf53488f 100644 --- a/cmd/devp2p/internal/ethtest/testdata/headfcu.json +++ b/cmd/devp2p/internal/ethtest/testdata/headfcu.json @@ -4,9 +4,9 @@ "method": "engine_forkchoiceUpdatedV1", "params": [ { - "headBlockHash": "0x5963f533df1abbcf81b0e74089902c77112c129855f09a26dbd15e5d034dbf61", - "safeBlockHash": "0x5963f533df1abbcf81b0e74089902c77112c129855f09a26dbd15e5d034dbf61", - "finalizedBlockHash": "0x5963f533df1abbcf81b0e74089902c77112c129855f09a26dbd15e5d034dbf61" + "headBlockHash": "0x6cbff26011501e62103a791266876e8af1a5399b7b9aaa37de3abe2a9e56d2de", + "safeBlockHash": "0x6cbff26011501e62103a791266876e8af1a5399b7b9aaa37de3abe2a9e56d2de", + "finalizedBlockHash": "0x6cbff26011501e62103a791266876e8af1a5399b7b9aaa37de3abe2a9e56d2de" }, null ] diff --git a/cmd/devp2p/internal/ethtest/testdata/headstate.json b/cmd/devp2p/internal/ethtest/testdata/headstate.json index 85ef35872..c914c032c 100644 --- a/cmd/devp2p/internal/ethtest/testdata/headstate.json +++ b/cmd/devp2p/internal/ethtest/testdata/headstate.json @@ -1,5 +1,5 @@ { - "root": "6c95616f8f988fb794ba25b6027b4643f4cab89f03d19a317a26561bf07392cd", + "root": "9f2b9986ee9bcd0a99033304705f7c6f4eb591b2612b6ffb99e6ce7f3882ea58", "accounts": { "0x0000000000000000000000000000000000001000": { "balance": "0", @@ -25,7 +25,7 @@ "0x0000000000000000000000000000000000001001": { "balance": "0", "nonce": 0, - "root": "0xc714c2420d4825c0dbb7dc7f879ec63ceb1af4dd860004ed47b581c297e0f2fc", + "root": "0xed49383e386105243e76233b58df0a5c3880bb3112d7a6f56cd9650c65660b77", "codeHash": "0xb5ce66a9f8c1a08247521c60191f8b11e31e472d8dc26ea163e66de307303dac", "code": "0x608060405234801561001057600080fd5b506004361061035d5760003560e01c8063774c9ce2116101d3578063bfbd7f4c11610104578063e169eca1116100a2578063eeaf68161161007c578063eeaf681614610890578063f9bf4553146108a3578063facd743b146108b6578063feac729d146108c957600080fd5b8063e169eca114610822578063e1b526b014610856578063eb1133ee1461086957600080fd5b8063deaa406e116100de578063deaa406e146107b5578063dfe5b236146107de578063e0a8f6f5146107e6578063e14a9da6146107f957600080fd5b8063bfbd7f4c1461076f578063c7f758a814610782578063c8541fe0146107a257600080fd5b806398951b5611610171578063a67bdb911161014b578063a67bdb911461070c578063a6c96cad1461071f578063a6f324f214610746578063a96b3a921461074f57600080fd5b806398951b56146106bf5780639d497366146106d2578063a11f9caa146106e557600080fd5b8063824ea8ed116101ad578063824ea8ed146106705780638280a25a146106915780638465fc631461069957806385752d03146106ac57600080fd5b8063774c9ce21461064c5780637c5a43ec146106545780637f4b33e91461066757600080fd5b806335efc734116102ad57806363bc2f441161024b5780636ad89315116102255780636ad89315146105e157806370a78608146105ea57806373098faf1461060a57806376b826231461063957600080fd5b806363bc2f441461059f57806365257410146105c6578063657ceef6146105d957600080fd5b80635890ef79116102875780635890ef791461054f5780635c646aa6146105645780635ce9284f14610577578063638693281461058a57600080fd5b806335efc734146104ec5780633bcb5a7d14610515578063563123e61461052857600080fd5b80630f43a6771161031a5780631c189d18116102f45780631c189d181461047457806320a302681461048757806324b858c8146104b2578063291795f9146104c557600080fd5b80630f43a67714610427578063132e578b1461042f5780631703a0181461044f57600080fd5b8063011f78c014610362578063013cf08b1461037d578063040bba71146103a757806308ae4b0c146103af5780630d61b519146103fb5780630e12ebd71461041e575b600080fd5b61036a600381565b6040519081526020015b60405180910390f35b61039061038b366004613b7a565b6108d2565b6040516103749b9a99989796959493929190613c15565b61036a6109d4565b6103df6103bd366004613cad565b60056020526000908152604090205460ff811690610100900463ffffffff1682565b60408051921515835263ffffffff909116602083015201610374565b61040e610409366004613b7a565b6109ed565b6040519015158152602001610374565b61036a600c5481565b61036a610a0d565b61036a61043d366004613b7a565b600a6020526000908152604090205481565b60045461045f9063ffffffff1681565b60405163ffffffff9091168152602001610374565b61040e610482366004613cca565b610a19565b61049a610495366004613cf6565b610a99565b6040516001600160a01b039091168152602001610374565b61040e6104c0366004613b7a565b610b08565b61036a7fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d81565b61049a6104fa366004613cad565b6035602052600090815260409020546001600160a01b031681565b61040e610523366004613b7a565b610b1f565b61036a7f3dbc1eb57270fd00d1185f7cc6dad1739ab2a199ec5d792e8797b112105abf9481565b610557610ce0565b6040516103749190613d18565b61036a610572366004613d77565b610cec565b61036a610585366004613b7a565b610e92565b61059d610598366004613cad565b610eb4565b005b61036a7f2e7eab62cb105bbcf2673dc7e79b70b7501abec6a6b72746bd2f6057382a472481565b61049a6105d4366004613cf6565b611133565b61036a600181565b61036a60015481565b6105fd6105f8366004613cad565b61116b565b6040516103749190613db0565b61040e610618366004613cad565b600c546001600160a01b039091166000908152600b60205260409020541090565b61059d610647366004613e0c565b611205565b61036a60ff81565b61045f610662366004613b7a565b611413565b61036a60005481565b61068361067e366004613b7a565b611461565b604051610374929190613e8f565b61036a603081565b61040e6106a7366004613b7a565b611521565b61040e6106ba366004613cca565b611703565b61059d6106cd366004613b7a565b611743565b61036a6106e0366004613ead565b61175d565b61036a7fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb81565b61036a61071a366004613b7a565b611865565b61036a7fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b5881565b61036a60395481565b61036a61075d366004613cad565b600b6020526000908152604090205481565b61036a61077d366004613d77565b61191b565b610795610790366004613b7a565b611a8c565b6040516103749190613eca565b61059d6107b0366004613b7a565b611c55565b61036a6107c3366004613cad565b6001600160a01b03166000908152600b602052604090205490565b61036a606081565b61059d6107f4366004613b7a565b611c6b565b61049a610807366004613cad565b6036602052600090815260409020546001600160a01b031681565b61049a610830366004613fa2565b80516020818301810180516038825292820191909301209152546001600160a01b031681565b61040e610864366004613b7a565b611d75565b61036a7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b81565b61036a61089e366004613b7a565b611e44565b60325461049a906001600160a01b031681565b61040e6108c4366004613cad565b611ee7565b61036a60025481565b600760208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701549787018054969895979496939592946001600160a01b0383169463ffffffff600160a01b8504811695600160c01b8604821695600160e01b90049091169360ff909116929161095190614053565b80601f016020809104026020016040519081016040528092919081815260200182805461097d90614053565b80156109ca5780601f1061099f576101008083540402835291602001916109ca565b820191906000526020600020905b8154815290600101906020018083116109ad57829003601f168201915b505050505090508b565b6000633b9aca006039546109e8919061409d565b905090565b6000816109f981611ef4565b610a04836000611fb0565b91505b50919050565b60006109e860336122ce565b6000610a24826122d8565b6000818152600760205260408120600181015492945091610a4690869061230a565b60018301546000908152600660205260409020549091508110610a6e57600092505050610a93565b60ff811115610a8257600092505050610a93565b600290910154600190911b16151590505b92915050565b600080610aa58461235e565b60008181526006602052604090208054919250908410610ad857604051634e23d03560e01b815260040160405180910390fd5b808481548110610aea57610aea6140bf565b6000918252602090912001546001600160a01b031695945050505050565b600081610b1481611ef4565b610a04836001611fb0565b60008060076000610b2f856122d8565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff166007811115610bde57610bde613b93565b6007811115610bef57610bef613b93565b8152602001600782018054610c0390614053565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2f90614053565b8015610c7c5780601f10610c5157610100808354040283529160200191610c7c565b820191906000526020600020905b815481529060010190602001808311610c5f57829003601f168201915b505050505081525050905060016007811115610c9a57610c9a613b93565b8161012001516007811115610cb157610cb1613b93565b03610cd7576000548160600151610cc891906140d5565b4211610cd75750600192915050565b50600092915050565b60606109e8603361238c565b336000908152600560205260408120805460ff16610d1d576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b038416610d445760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff1615610d7e5760405163a929afd160e01b815260040160405180910390fd5b60015460009081526006602052604090205460ff8110610db15760405163443afd7960e01b815260040160405180910390fd5b6000610dbe8260016140d5565b905080600103610df4578463ffffffff16600114610def5760405163d173577960e01b815260040160405180910390fd5b610e2c565b60028563ffffffff161080610e0e5750808563ffffffff16115b15610e2c5760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff8716818301528151808203830181526060909101909152610e857fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb82612399565b94505050505b5092915050565b600080610e9e8361235e565b6000908152600660205260409020549392505050565b336000908152600560205260409020805460ff16610ee5576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b038316610f0d5760405163ddf1d6dd60e01b815260040160405180910390fd5b826001600160a01b0316816001600160a01b031603610f3f5760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03831660009081526005602052604090205460ff1615610f795760405163a929afd160e01b815260040160405180910390fd5b600154600081815260066020526040812080549091805b8281101561106457856001600160a01b0316848281548110610fb457610fb46140bf565b6000918252602090912001546001600160a01b0316036110525787848281548110610fe157610fe16140bf565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790558782526008815260408083208a851680855292528083208054948d168452908320805463ffffffff90951663ffffffff1995861617905591528054909116905560019150611064565b8061105c816140ed565b915050610f90565b5080611083576040516305031d1160e31b815260040160405180910390fd5b604080518082018252600181524263ffffffff90811660208084019182526001600160a01b038c81166000818152600590935286832095518654945164ffffffffff1990951690151564ffffffff00191617610100949095169390930293909317909355908816808352838320805460ff1916905592519092917f05d866cd9c6000815d031b7ce30f30f643766eba16be13cff25924dc8ad8209291a361112a858861260e565b50505050505050565b6006602052816000526040600020818154811061114f57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6037602052600090815260409020805461118490614053565b80601f01602080910402602001604051908101604052809291908181526020018280546111b090614053565b80156111fd5780601f106111d2576101008083540402835291602001916111fd565b820191906000526020600020905b8154815290600101906020018083116111e057829003601f168201915b505050505081565b336000908152600560205260409020805460ff16611236576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b03861661125d57604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b0386811660009081526035602052604090205416158015906112a057506001600160a01b03868116600090815260356020526040902054163314155b156112be57604051633d02709560e11b815260040160405180910390fd5b6112ca8585858561268c565b336000908152603660205260408082205490516001600160a01b0390911691906038906112fa9089908990614106565b908152604051908190036020019020546001600160a01b0316148015906113545750806001600160a01b031660388787604051611338929190614106565b908152604051908190036020019020546001600160a01b031614155b156113725760405163968978b960e01b815260040160405180910390fd5b6001600160a01b0381166113905761138b8787876127af565b61112a565b866001600160a01b0316816001600160a01b03160361140757806001600160a01b0316603887876040516113c5929190614106565b908152604051908190036020019020546001600160a01b0316036113fc576040516366b9db0b60e11b815260040160405180910390fd5b61138b81878761280a565b61112a8188888861285a565b60008061141f8361235e565b60008181526009602052604081205491925063ffffffff9091169081900361145a5760405163d173577960e01b815260040160405180910390fd5b9392505050565b600080821580611472575060025483115b156114835750600192600092509050565b60008381526007602052604090206002600682015460ff1660078111156114ac576114ac613b93565b146114be575060029360009350915050565b60005481600301546114d091906140d5565b4211156114e4575060039360009350915050565b6000848152600a60205260409020546003811061150957506004946000945092505050565b6000611516826003614116565b935093505050915091565b60008060076000611531856122d8565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff1660078111156115e0576115e0613b93565b60078111156115f1576115f1613b93565b815260200160078201805461160590614053565b80601f016020809104026020016040519081016040528092919081815260200182805461163190614053565b801561167e5780601f106116535761010080835404028352916020019161167e565b820191906000526020600020905b81548152906001019060200180831161166157829003601f168201915b50505050508152505090506002600781111561169c5761169c613b93565b81610120015160078111156116b3576116b3613b93565b146116c15750600092915050565b60005481606001516116d391906140d5565b4211156116e35750600092915050565b8060c0015163ffffffff168160e0015163ffffffff161015915050919050565b60008061170f8361235e565b60009081526008602090815260408083206001600160a01b038816845290915290205463ffffffff16151591505092915050565b8061174d81611ef4565b6117598260018061286f565b5050565b336000908152600560205260408120805460ff1661178e576040516305031d1160e31b815260040160405180910390fd5b60018054600090815260066020526040902054908190036117d5578363ffffffff166001146117d05760405163d173577960e01b815260040160405180910390fd5b61180d565b60028463ffffffff1610806117ef5750808463ffffffff16115b1561180d5760405163d173577960e01b815260040160405180910390fd5b6040805163ffffffff8616602082015260009101604051602081830303815290604052905061185c7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b82612399565b95945050505050565b336000908152600560205260408120805460ff16611896576040516305031d1160e31b815260040160405180910390fd5b60018310806118a55750603283115b156118c35760405163e46113f560e01b815260040160405180910390fd5b6000836040516020016118d891815260200190565b60405160208183030381529060405290506119137fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b5882612399565b949350505050565b336000908152600560205260408120805460ff1661194c576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff16611985576040516305031d1160e31b815260040160405180910390fd5b600180546000908152600660205260409020549081116119b85760405163d173577960e01b815260040160405180910390fd5b60006119c5600183614116565b9050806001036119fb578463ffffffff166001146119f65760405163d173577960e01b815260040160405180910390fd5b611a33565b60028563ffffffff161080611a155750808563ffffffff16115b15611a335760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff8716818301528151808203830181526060909101909152610e857fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d82612399565b611aeb6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052906101208201908152602001606081525090565b611af4826122d8565b60008181526007602081815260409283902083516101608101855281548152600182015492810192909252600281015493820193909352600383015460608201526004830154608082015260058301546001600160a01b03811660a083015263ffffffff600160a01b8204811660c0840152600160c01b8204811660e0840152600160e01b9091041661010082015260068301549395509261012084019160ff90911690811115611ba757611ba7613b93565b6007811115611bb857611bb8613b93565b8152602001600782018054611bcc90614053565b80601f0160208091040260200160405190810160405280929190818152602001828054611bf890614053565b8015611c455780601f10611c1a57610100808354040283529160200191611c45565b820191906000526020600020905b815481529060010190602001808311611c2857829003601f168201915b5050505050815250509050919050565b80611c5f81611ef4565b6117598260008061286f565b80611c7581611ef4565b60008281526007602052604090206001600682015460ff166007811115611c9e57611c9e613b93565b14611cbc576040516377036cbb60e01b815260040160405180910390fd5b60058101546001600160a01b03163314611ce957604051637d1b73b960e01b815260040160405180910390fd5b60058101546001600160c01b90910463ffffffff161180611d1a57506005810154600160e01b900463ffffffff1615155b15611d38576040516355fe710960e01b815260040160405180910390fd5b611d43836004612c8b565b604051339084907f74c34a008ce735d9fcf0bd03a9b238d212ad4c441c020661f4ffbb6442645b8590600090a3505050565b600081611d8181611ef4565b60008381526007602052604090206001600682015460ff166007811115611daa57611daa613b93565b14158015611dd157506002600682015460ff166007811115611dce57611dce613b93565b14155b15611de0576000925050610a07565b6000548160030154611df291906140d5565b4211611e02576000925050610a07565b611e0d846005612c8b565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a35060019392505050565b336000908152600560205260408120805460ff16611e75576040516305031d1160e31b815260040160405180910390fd5b6039548303611e975760405163d224a7bb60e01b815260040160405180910390fd5b600083604051602001611eac91815260200190565b60405160208183030381529060405290506119137f3dbc1eb57270fd00d1185f7cc6dad1739ab2a199ec5d792e8797b112105abf9482612399565b6000610a93603383612cfb565b600060076000611f03846122d8565b815260200190815260200160002090506000611f2333836001015461230a565b600183015460009081526006602052604090208054919250908210611f5b576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b0316818381548110611f7757611f776140bf565b6000918252602090912001546001600160a01b031614611faa576040516305031d1160e31b815260040160405180910390fd5b50505050565b6000611fba612d1d565b821580611fc8575060025483115b15611fe657604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206002600682015460ff16600781111561200f5761200f613b93565b1461202d57604051633c7e994560e11b815260040160405180910390fd5b600581015463ffffffff600160a01b82048116600160c01b90920416101561206857604051638af69cf160e01b815260040160405180910390fd5b600054816003015461207a91906140d5565b4211156120c35761208c846005612c8b565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a360009150506122c4565b6000848152600a602052604090205460031161215a576120e4846006612c8b565b604080518082018252601781527f4d617820726574727920636f756e74207265616368656400000000000000000060208201529051339186917f68d5d5ea31f430b04112f5edc367c01af04da56d10cd663fbfbc4fbe5f509c209161214891613db0565b60405180910390a360009150506122c4565b6000848152600a60205260408120805491612174836140ed565b9190505550612213816000015482600701805461219090614053565b80601f01602080910402602001604051908101604052809291908181526020018280546121bc90614053565b80156122095780601f106121de57610100808354040283529160200191612209565b820191906000526020600020905b8154815290600101906020018083116121ec57829003601f168201915b5050505050612d47565b9150811561226357612226846003612c8b565b60405160018152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a36122c2565b821561227957612274846006612c8b565b612289565b60068101805460ff191660021790555b60405160008152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a35b505b610a936000600355565b6000610a93825490565b60008115806122e8575060025482115b1561230657604051631dc0650160e31b815260040160405180910390fd5b5090565b60008181526008602090815260408083206001600160a01b038616845290915281205463ffffffff1680820361234557600019915050610a93565b61235060018261412d565b63ffffffff16949350505050565b600081158061236e575060015482115b15612306576040516315ed869560e21b815260040160405180910390fd5b6060600061145a83612e90565b336000908152600560205260408120805460ff166123ca576040516305031d1160e31b815260040160405180910390fd5b6000546000036123ed576040516387321fdd60e01b815260040160405180910390fd5b600c54336000908152600b60205260409020541061241e5760405163090b564b60e01b815260040160405180910390fd5b60026000815461242d906140ed565b918290555060408051610160810182528681526001805460208301526000928201839052426060830152608082018390523360a083015260045463ffffffff1660c083015260e0820183905261010082019290925291935061012082019081526020908101859052600084815260078083526040918290208451815592840151600180850191909155918401516002840155606084015160038401556080840151600484015560a084015160058401805460c087015160e08801516101008901516001600160a01b039095166001600160c01b031990931692909217600160a01b63ffffffff92831602176001600160c01b0316600160c01b928216929092026001600160e01b031691909117600160e01b91909316029190911790556101208401516006840180549193909260ff1990921691849081111561257257612572613b93565b02179055506101408201518051612593916007840191602090910190613a3b565b505060015460045460405133935085927f830652010a654c24b39890c16f53e6f6179becc61702ecd9a8c88461c2ff941a926125da928a929163ffffffff16908a90614152565b60405180910390a3336000908152600b602052604081208054916125fd836140ed565b9190505550610e8b8260018061286f565b6001600160a01b03808316600090815260366020526040902054168015612687576001600160a01b03808316600081815260366020818152604080842080548789166001600160a01b03199182168117909255908552603583528185208054821690961790955594881683525291909120805490911690555b505050565b603083146126ad57604051631e3e9f4160e21b815260040160405180910390fd5b606081146126ce57604051634be6321b60e01b815260040160405180910390fd5b60325460405160009182916001600160a01b03909116906126f9908890889088908890602001614187565b60408051601f1981840301815290829052612713916141a9565b600060405180830381855afa9150503d806000811461274e576040519150601f19603f3d011682016040523d82523d6000602084013e612753565b606091505b509150915081612776576040516320e5cb5360e01b815260040160405180910390fd5b8080602001905181019061278a91906141c5565b6127a757604051631bb31e3560e31b815260040160405180910390fd5b505050505050565b6127ba603384612eec565b5033600081815260366020908152604080832080546001600160a01b0389166001600160a01b03199182168117909255908452603590925290912080549091169091179055612687838383612f01565b6001600160a01b038316600090815260376020526040908190209051603891612832916141e7565b90815260405190819003602001902080546001600160a01b0319169055612687838383612f01565b6128648433612f6c565b611faa8383836127af565b82158061287d575060025483115b1561289b57604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206001600682015460ff1660078111156128c4576128c4613b93565b141580156128eb57506002600682015460ff1660078111156128e8576128e8613b93565b14155b15612909576040516377036cbb60e01b815260040160405180910390fd5b600054816003015461291b91906140d5565b4211156129605761292d846005612c8b565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a350505050565b60018101546000612971338361230a565b600083815260066020526040902080549192509082106129a4576040516305031d1160e31b815260040160405180910390fd5b60ff8211156129c65760405163443afd7960e01b815260040160405180910390fd5b60028401546001831b908116156129f05760405163080fc0bd60e11b815260040160405180910390fd5b600285018054821790558615612b52576005850154600090612a2090600160c01b900463ffffffff166001614282565b60058701805463ffffffff60c01b1916600160c01b63ffffffff848116918202929092179283905560408051600181526020810192909252600160e01b90930490911681830152905191925033918b917f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc05919081900360600190a3600586015463ffffffff600160a01b909104811690821610612b4c576002600687015460ff166007811115612ad257612ad2613b93565b14612b395760068601805460ff1916600217905560058601546040805163ffffffff8481168252600160e01b909304909216602083015233918b917f5064fb9bf50f615c47cc24c49119ba31d2c1a83ad6aed3b226cd42005524b7f4910160405180910390a35b8615612b4c57612b4a896000611fb0565b505b50612c81565b6005850154600090612b7290600160e01b900463ffffffff166001614282565b6005870180546001600160e01b0316600160e01b63ffffffff84811691820292909217928390556040805160008152600160c01b90940490921660208401529082015290915033908a907f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc059060600160405180910390a360058601548354600091612c0b91600160a01b90910463ffffffff169061412d565b90508063ffffffff168263ffffffff161115612c7e57612c2c8a6007612c8b565b60058701546040805163ffffffff600160c01b90930483168152918416602083015233918c917f6fa60fd92b2557298bb7b39e7b538b3f00ebf09b9f056bdeac7f0e5d57e8fcbb910160405180910390a35b50505b5050505050505050565b60008281526007602081905260409091206006018054839260ff19909116906001908490811115612cbe57612cbe613b93565b02179055506003816007811115612cd757612cd7613b93565b03612cf2576000828152600760205260409020426004909101555b61175982613010565b6001600160a01b0381166000908152600183016020526040812054151561145a565b600354600103612d40576040516306fda65d60e31b815260040160405180910390fd5b6001600355565b60007fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb8303612da05760008083806020019051810190612d8791906142aa565b91509150612d95828261306f565b600192505050610a93565b7fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d8303612dec5760008083806020019051810190612dde91906142aa565b91509150612d9582826133b7565b7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b8303612e3e57600082806020019051810190612e2991906142d9565b9050612e3481613678565b6001915050610a93565b7fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b588303612e8657600082806020019051810190612e7b91906142f6565b9050612e348161377b565b61145a83836137ed565b606081600001805480602002602001604051908101604052809291908181526020018280548015612ee057602002820191906000526020600020905b815481526020019060010190808311612ecc575b50505050509050919050565b600061145a836001600160a01b038416613837565b6001600160a01b0383166000908152603760205260409020612f24908383613abb565b508260388383604051612f38929190614106565b90815260405190819003602001902080546001600160a01b03929092166001600160a01b0319909216919091179055505050565b612f77603383613886565b506001600160a01b03808316600081815260356020908152604080832080546001600160a01b0319908116909155948616835260368252808320805490951690945591815260379091528190209051603891612fd2916141e7565b908152604080516020928190038301902080546001600160a01b03191690556001600160a01b03841660009081526037909252812061175991613b2f565b6000818152600760209081526040808320600501546001600160a01b0316808452600b9092529091205415611759576001600160a01b0381166000908152600b602052604081208054916130638361430f565b91905055505050565b50565b6001600160a01b03821660009081526005602052604090205460ff16156130a95760405163a929afd160e01b815260040160405180910390fd5b6001600160a01b0382166130d05760405163ddf1d6dd60e01b815260040160405180910390fd5b60008060006130dd61389b565b8154929550909350915060006130f48260016140d5565b905060ff82106131175760405163443afd7960e01b815260040160405180910390fd5b8060010361314b578563ffffffff166001146131465760405163d173577960e01b815260040160405180910390fd5b613183565b60028663ffffffff1610806131655750808663ffffffff16115b156131835760405163d173577960e01b815260040160405180910390fd5b60005b8281101561323c5760008582815481106131a2576131a26140bf565b6000918252602080832090910154895460018181018c558b85529290932090920180546001600160a01b0319166001600160a01b0390931692831790559091506131ed9083906140d5565b60008681526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff90921691909117905580613234816140ed565b915050613186565b5084546001808201875560008781526020902090910180546001600160a01b0319166001600160a01b038a161790556132769083906140d5565b60008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff1990811663ffffffff978816179091558251808401845260018152428716818601908152838752600586529584902090518154965164ffffffffff1990971690151564ffffffff001916176101009688169690960295909517909455600480549485168c87169081179091558a5483519081529384015292909316927fd693483bf3059d721fcb091390377153e45c1b15c85015ea8c5547b92960ff56910160405180910390a26040805163ffffffff8084168252891660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a15050506000908152600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b6001600160a01b03821660009081526005602052604090205460ff166133f0576040516305031d1160e31b815260040160405180910390fd5b60008060006133fd61389b565b815492955090935091506000613414600183614116565b9050806000036134375760405163d173577960e01b815260040160405180910390fd5b8060010361346b578563ffffffff166001146134665760405163d173577960e01b815260040160405180910390fd5b6134a3565b60028663ffffffff1610806134855750808663ffffffff16115b156134a35760405163d173577960e01b815260040160405180910390fd5b6000805b8381101561356c5760008682815481106134c3576134c36140bf565b6000918252602090912001546001600160a01b0390811691508a1681036134ea575061355a565b87546001810189556000898152602090200180546001600160a01b0319166001600160a01b03831617905561351e836140ed565b60008781526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff831617905591505b80613564816140ed565b9150506134a7565b5060008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff199081169091556005845293829020805460ff191690556004805494851663ffffffff8d81169182179092558b5484519081529485015290931692917fab15a70783712986077aea9a4cbfd4c1561dd8672489037c581fbaf8fc658516910160405180910390a26040805163ffffffff80841682528a1660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a1613648896138d6565b505050600091825250600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b60018054600090815260066020526040902054908190036136bf578163ffffffff166001146136ba5760405163d173577960e01b815260040160405180910390fd5b6136f7565b60028263ffffffff1610806136d95750808263ffffffff16115b156136f75760405163d173577960e01b815260040160405180910390fd5b6004805463ffffffff84811663ffffffff1983168117909355604080519190921680825260208201939093527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a150506001546000908152600960205260409020805463ffffffff191663ffffffff92909216919091179055565b600181108061378a5750603281115b156137a85760405163e46113f560e01b815260040160405180910390fd5b600c80549082905560408051828152602081018490527f56b9de3a8fc94721b6e3f917d89308667325aefa7d3d6d99b42acda37f3855bf910160405180910390a15050565b60007f3dbc1eb57270fd00d1185f7cc6dad1739ab2a199ec5d792e8797b112105abf948303610cd75760008280602001905181019061382c91906142f6565b9050612e3481613901565b600081815260018301602052604081205461387e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a93565b506000610a93565b600061145a836001600160a01b038416613948565b60008060008060015490508060016138b391906140d5565b600091825260066020526040808320828452922060018290559591945092509050565b6001600160a01b03808216600090815260366020526040902054168015611759576117598183612f6c565b6039805490829055604080518281526020810184905233917f535d54b8a14e2287f10efd7add38eca14bcf44eb31651abf8eec2499eba393a3910160405180910390a25050565b60008181526001830160205260408120548015613a3157600061396c600183614116565b855490915060009061398090600190614116565b90508181146139e55760008660000182815481106139a0576139a06140bf565b90600052602060002001549050808760000184815481106139c3576139c36140bf565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806139f6576139f6614326565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a93565b6000915050610a93565b828054613a4790614053565b90600052602060002090601f016020900481019282613a695760008555613aaf565b82601f10613a8257805160ff1916838001178555613aaf565b82800160010185558215613aaf579182015b82811115613aaf578251825591602001919060010190613a94565b50612306929150613b65565b828054613ac790614053565b90600052602060002090601f016020900481019282613ae95760008555613aaf565b82601f10613b025782800160ff19823516178555613aaf565b82800160010185558215613aaf579182015b82811115613aaf578235825591602001919060010190613b14565b508054613b3b90614053565b6000825580601f10613b4b575050565b601f01602090049060005260206000209081019061306c91905b5b808211156123065760008155600101613b66565b600060208284031215613b8c57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60088110613bb957613bb9613b93565b9052565b60005b83811015613bd8578181015183820152602001613bc0565b83811115611faa5750506000910152565b60008151808452613c01816020860160208601613bbd565b601f01601f19169290920160200192915050565b8b8152602081018b9052604081018a905260608101899052608081018890526001600160a01b03871660a082015263ffffffff86811660c083015285811660e083015284166101008201526000610160613c73610120840186613ba9565b80610140840152613c8681840185613be9565b9e9d5050505050505050505050505050565b6001600160a01b038116811461306c57600080fd5b600060208284031215613cbf57600080fd5b813561145a81613c98565b60008060408385031215613cdd57600080fd5b8235613ce881613c98565b946020939093013593505050565b60008060408385031215613d0957600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015613d595783516001600160a01b031683529284019291840191600101613d34565b50909695505050505050565b63ffffffff8116811461306c57600080fd5b60008060408385031215613d8a57600080fd5b8235613d9581613c98565b91506020830135613da581613d65565b809150509250929050565b60208152600061145a6020830184613be9565b60008083601f840112613dd557600080fd5b50813567ffffffffffffffff811115613ded57600080fd5b602083019150836020828501011115613e0557600080fd5b9250929050565b600080600080600060608688031215613e2457600080fd5b8535613e2f81613c98565b9450602086013567ffffffffffffffff80821115613e4c57600080fd5b613e5889838a01613dc3565b90965094506040880135915080821115613e7157600080fd5b50613e7e88828901613dc3565b969995985093965092949392505050565b6040810160058410613ea357613ea3613b93565b9281526020015290565b600060208284031215613ebf57600080fd5b813561145a81613d65565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a0830151613f1960c08401826001600160a01b03169052565b5060c083015163ffffffff811660e08401525060e0830151610100613f458185018363ffffffff169052565b8401519050610120613f5e8482018363ffffffff169052565b8401519050610140613f7284820183613ba9565b840151610160848101529050611913610180840182613be9565b634e487b7160e01b600052604160045260246000fd5b600060208284031215613fb457600080fd5b813567ffffffffffffffff80821115613fcc57600080fd5b818401915084601f830112613fe057600080fd5b813581811115613ff257613ff2613f8c565b604051601f8201601f19908116603f0116810190838211818310171561401a5761401a613f8c565b8160405282815287602084870101111561403357600080fd5b826020860160208301376000928101602001929092525095945050505050565b600181811c9082168061406757607f821691505b602082108103610a0757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000826140ba57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600082198211156140e8576140e8614087565b500190565b6000600182016140ff576140ff614087565b5060010190565b8183823760009101908152919050565b60008282101561412857614128614087565b500390565b600063ffffffff8381169083168181101561414a5761414a614087565b039392505050565b84815283602082015263ffffffff8316604082015260806060820152600061417d6080830184613be9565b9695505050505050565b8385823760008482016000815283858237600093019283525090949350505050565b600082516141bb818460208701613bbd565b9190910192915050565b6000602082840312156141d757600080fd5b8151801515811461145a57600080fd5b600080835481600182811c91508083168061420357607f831692505b6020808410820361422257634e487b7160e01b86526022600452602486fd5b818015614236576001811461424757614274565b60ff19861689528489019650614274565b60008a81526020902060005b8681101561426c5781548b820152908501908301614253565b505084890196505b509498975050505050505050565b600063ffffffff8083168185168083038211156142a1576142a1614087565b01949350505050565b600080604083850312156142bd57600080fd5b82516142c881613c98565b6020840151909250613da581613d65565b6000602082840312156142eb57600080fd5b815161145a81613d65565b60006020828403121561430857600080fd5b5051919050565b60008161431e5761431e614087565b506000190190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212207819bc7789e244ae936f8cdde7a3dcfa6f4c13e4e897ade91d97e98911867f3564736f6c634300080e0033", "storage": { @@ -36,19 +36,19 @@ "0x0000000000000000000000000000000000000000000000000000000000000032": "b00001", "0x0000000000000000000000000000000000000000000000000000000000000033": "01", "0x0000000000000000000000000000000000000000000000000000000000000039": "048c27395000", - "0x028dcfa4bfbc0247b35b0bda5a23aa67d17cdd3ac2268b9991fddf4970ecedd5": "97c400fd91b90fa95292799990277b547df8b87cb866c2e77ac0e0ffa2a6558e", - "0x028dcfa4bfbc0247b35b0bda5a23aa67d17cdd3ac2268b9991fddf4970ecedd6": "f7087a0785870202c45dd49c5de147b300000000000000000000000000000000", - "0x1e69254cd49a2c45945d52e976b9871368a351652786da8a1f1463e2e665f936": "01", + "0x0b851d8cc2d7feaca604f32212764c413d624fc7c40f484d1008902bf6d8c4d4": "45dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x36f6cb310a5204ca809a30b476706146d10378ba8ac1e6fb04dbfdab6fa18366": "92272a6e9692aa2ffe724257fe911e17189c5081b73c55ba1aacbd81248b6261", + "0x36f6cb310a5204ca809a30b476706146d10378ba8ac1e6fb04dbfdab6fa18367": "fbfc5578c46407b94ba8dcdf6f8c926b00000000000000000000000000000000", "0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31": "01", - "0x3e8da299fe59cecc53e28d470b241fd34828ffde97ea9bb1219f65edac4f64e1": "61", - "0x4c29547f452fd736598991b8bb296e53e86caa5c3c4364ecfeea305bb7b22fd0": "7a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x6736ab4999a73108ab8ac21ffd41cc04433a97cf07b814c9219acbf870701a70": "01", - "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "7a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82": "7a2b5390bb632269133d3b7eda466b4b44bf2762", - "0x8c408ba05a2c1c38f8f835492b4e7a17c1a4979a24a23659ed0847b181afa169": "7a2b5390bb632269133d3b7eda466b4b44bf2762", + "0x800ab95231c8300368c5183ff4f29b54267dc887ff4bdba9a3c7d261e8e23357": "61", + "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "45dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x82a75bdeeae8604d839476ae9efd8b0e15aa447e21bfd7f41283bb54e22c9a82": "45dfd9f6da52abaee54ad49226c698e45b2f3777", + "0x882fcd6ad65d6b881b736e03202e72aa4820efbf85e957a2eefa1db99e6b0bf7": "45dfd9f6da52abaee54ad49226c698e45b2f3777", "0x92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36": "01", - "0x9fd22f50db652b5a02069e1e70a1d4e05cfa705ac6dce344b87e5aec62c902bf": "7a2b5390bb632269133d3b7eda466b4b44bf2762", - "0xa744f52b287c3e302328427e079fff658bea984284c892e1cedca11e3fd3bf76": "01" + "0x989e0935e5eb704164e806605aa7236ab3b0491c1532892656ca9146005605bf": "01", + "0x9d70ac842bcd0aa6584820c5c41e2ff619d598e37cf249fbc4e4d23d6aa86d5d": "01", + "0xab96d7f7ff423c5cf59be6a79eba33259c631859a01085a9a08ff1952f4c7b61": "45dfd9f6da52abaee54ad49226c698e45b2f3777", + "0xeca75a8ba86c40655ff183321d57ce0e05e5140e90ba59f0e7aec436354ee04b": "01" }, "address": "0x0000000000000000000000000000000000001001", "key": "0x6fbcbed9964f09cf739fa70d7adb88c28fe4fbf10fd9bd33b4c6c984f504251a" @@ -103,20 +103,12 @@ "0x0000000000000000000000000000000000001004": { "balance": "0", "nonce": 0, - "root": "0x9ad858133a78939964250b9fb40e572e4f01b59de6452764177dc51737ad3d50", + "root": "0x3b6c51d02d35d92523b42a272bfdbfbded426556408a5836dead603e5f7c3cff", "codeHash": "0x5a6e0f04acf2122487c1c512dc925d5f85a30c4bb6e2a60abba5db009ba472ab", "code": "0x608060405234801561001057600080fd5b50600436106103e65760003560e01c8063820706e41161020a578063b7bb66d211610125578063d6491c55116100b8578063e1b526b011610087578063e1b526b014610a15578063e860cb8f14610a28578063eb1133ee14610a30578063fe575a8714610a57578063feac729d14610a6a57600080fd5b8063d6491c551461099f578063deaa406e146109c6578063e0a8f6f5146109ef578063e0fccde814610a0257600080fd5b8063c7f758a8116100f4578063c7f758a814610946578063c8541fe014610966578063ce236ec414610979578063cf44550e1461098c57600080fd5b8063b7bb66d2146108dd578063bfbd7f4c146108e5578063bfdddcc2146108f8578063c1b66bf21461091f57600080fd5b806398951b561161019d578063a6c96cad1161016c578063a6c96cad1461087b578063a96b3a92146108a2578063affe1400146108c2578063b20ccd16146108ca57600080fd5b806398951b561461081b5780639d4973661461082e578063a11f9caa14610841578063a67bdb911461086857600080fd5b806385752d03116101d957806385752d03146107bb578063911ad022146107ce57806393a8bb99146107e157806394d11082146107f457600080fd5b8063820706e414610761578063824ea8ed146107745780638465fc631461079557806384fd5477146107a857600080fd5b80635216de37116103055780636a6debd71161029857806377989bac1161026757806377989bac146106e45780637a1d67341461070b5780637c5a43ec146107325780637f4b33e9146107455780637f5d6dcc1461074e57600080fd5b80636a6debd71461069c5780636ad89315146106a457806373098faf146106ad578063774c9ce2146106dc57600080fd5b806363869328116102d4578063638693281461064557806363bc2f441461065a5780636525741014610681578063657ceef61461069457600080fd5b80635216de37146105e55780635c646aa6146105f85780635ce9284f1461060b5780636079a85a1461061e57600080fd5b80631c189d181161037d578063291795f91161034c578063291795f9146105785780632d6e57151461059f5780633bcb5a7d146105bf5780633d4c0452146105d257600080fd5b80631c189d181461050057806320a302681461051357806323e890961461053e57806324b858c81461056557600080fd5b80630d61b519116103b95780630d61b5191461048f5780630e12ebd7146104b2578063132e578b146104bb5780631703a018146104db57600080fd5b8063011f78c0146103eb578063013cf08b1461040657806308ae4b0c146104305780630d3212731461047c575b600080fd5b6103f3600381565b6040519081526020015b60405180910390f35b6104196104143660046149fe565b610a73565b6040516103fd9b9a99989796959493929190614a99565b61046061043e366004614b31565b60056020526000908152604090205460ff811690610100900463ffffffff1682565b60408051921515835263ffffffff9091166020830152016103fd565b6103f361048a366004614b31565b610b75565b6104a261049d3660046149fe565b610c4e565b60405190151581526020016103fd565b6103f3600c5481565b6103f36104c93660046149fe565b600a6020526000908152604090205481565b6004546104eb9063ffffffff1681565b60405163ffffffff90911681526020016103fd565b6104a261050e366004614b4e565b610c65565b610526610521366004614b7a565b610ce5565b6040516001600160a01b0390911681526020016103fd565b6103f37f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b81565b6104a26105733660046149fe565b610d54565b6103f37fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d81565b6105b26105ad366004614b7a565b610d6b565b6040516103fd9190614b9c565b6104a26105cd3660046149fe565b610d80565b6103f36105e0366004614b31565b610f41565b6103f36105f3366004614be9565b610fd9565b6103f3610606366004614c70565b6110b8565b6103f36106193660046149fe565b61125c565b6103f37ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee81565b610658610653366004614b31565b61127e565b005b6103f37f2e7eab62cb105bbcf2673dc7e79b70b7501abec6a6b72746bd2f6057382a472481565b61052661068f366004614b7a565b6114f3565b6103f3600181565b6103f361152b565b6103f360015481565b6104a26106bb366004614b31565b600c546001600160a01b039091166000908152600b60205260409020541090565b6103f360ff81565b6103f37f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a81565b6103f37f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e81565b6104eb6107403660046149fe565b61153b565b6103f360005481565b61052661075c3660046149fe565b611582565b6105b261076f366004614b7a565b61158f565b6107876107823660046149fe565b61159d565b6040516103fd929190614ca9565b6104a26107a33660046149fe565b61165d565b6104a26107b6366004614b31565b61183f565b6104a26107c9366004614b4e565b61197d565b6103f36107dc366004614be9565b6119bd565b6103f36107ef366004614b31565b611a92565b6103f37f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac381565b6106586108293660046149fe565b611b52565b6103f361083c366004614cc7565b611b6c565b6103f37fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb81565b6103f36108763660046149fe565b611c74565b6103f37fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b5881565b6103f36108b0366004614b31565b600b6020526000908152604090205481565b6105b2611d22565b6105266108d83660046149fe565b611d2e565b6105b2611d3b565b6103f36108f3366004614c70565b611d47565b6103f37fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed281565b6103f37fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a081565b6109596109543660046149fe565b611eb8565b6040516103fd9190614ce4565b6106586109743660046149fe565b612081565b6103f3610987366004614be9565b612097565b6103f361099a366004614b31565b6121a0565b6103f37fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b81565b6103f36109d4366004614b31565b6001600160a01b03166000908152600b602052604090205490565b6106586109fd3660046149fe565b612238565b6103f3610a10366004614be9565b612342565b6104a2610a233660046149fe565b61244b565b6103f361251a565b6103f37ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b81565b6104a2610a65366004614b31565b612525565b6103f360025481565b600760208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701549787018054969895979496939592946001600160a01b0383169463ffffffff600160a01b8504811695600160c01b8604821695600160e01b90049091169360ff9091169291610af290614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1e90614da6565b8015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b820191906000526020600020905b815481529060010190602001808311610b4e57829003601f168201915b505050505090508b565b336000908152600560205260408120805460ff16610ba6576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b038316610bcd576040516342bcdf7f60e11b815260040160405180910390fd5b610bd8603284612644565b15610bf657604051632ada027560e21b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b91015b60405160208183030381529060405261267e565b91505b50919050565b600081610c5a816128f3565b610c458360006129af565b6000610c7082612ccd565b6000818152600760205260408120600181015492945091610c92908690612cff565b60018301546000908152600660205260409020549091508110610cba57600092505050610cdf565b60ff811115610cce57600092505050610cdf565b600290910154600190911b16151590505b92915050565b600080610cf184612d53565b60008181526006602052604090208054919250908410610d2457604051634e23d03560e01b815260040160405180910390fd5b808481548110610d3657610d36614dda565b6000918252602090912001546001600160a01b031695945050505050565b600081610d60816128f3565b610c458360016129af565b6060610d7960348484612d81565b9392505050565b60008060076000610d9085612ccd565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff166007811115610e3f57610e3f614a17565b6007811115610e5057610e50614a17565b8152602001600782018054610e6490614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9090614da6565b8015610edd5780601f10610eb257610100808354040283529160200191610edd565b820191906000526020600020905b815481529060010190602001808311610ec057829003601f168201915b505050505081525050905060016007811115610efb57610efb614a17565b8161012001516007811115610f1257610f12614a17565b03610f38576000548160600151610f299190614e06565b4211610f385750600192915050565b50600092915050565b336000908152600560205260408120805460ff16610f72576040516305031d1160e31b815260040160405180910390fd5b610f7d603284612644565b610f9a576040516326a5b9a160e21b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac39101610c31565b336000908152600560205260408120805460ff1661100a576040516305031d1160e31b815260040160405180910390fd5b60005b838110156110765761104785858381811061102a5761102a614dda565b905060200201602081019061103f9190614b31565b603490612644565b611064576040516305da0e2560e11b815260040160405180910390fd5b8061106e81614e1e565b91505061100d565b506110ae7fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b8585604051602001610c31929190614e37565b91505b5092915050565b336000908152600560205260408120805460ff166110e9576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b0384166111105760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff161561114a5760405163a929afd160e01b815260040160405180910390fd5b60015460009081526006602052604090205460ff811061117d5760405163443afd7960e01b815260040160405180910390fd5b600061118a826001614e06565b9050806001036111c0578463ffffffff166001146111bb5760405163d173577960e01b815260040160405180910390fd5b6111f8565b60028563ffffffff1610806111da5750808563ffffffff16115b156111f85760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff87168183015281518082038301815260609091019091526112517fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb8261267e565b979650505050505050565b60008061126883612d53565b6000908152600660205260409020549392505050565b336000908152600560205260409020805460ff166112af576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b0383166112d75760405163ddf1d6dd60e01b815260040160405180910390fd5b826001600160a01b0316816001600160a01b0316036113095760405163ddf1d6dd60e01b815260040160405180910390fd5b6001600160a01b03831660009081526005602052604090205460ff16156113435760405163a929afd160e01b815260040160405180910390fd5b600154600081815260066020526040812080549091805b8281101561142e57856001600160a01b031684828154811061137e5761137e614dda565b6000918252602090912001546001600160a01b03160361141c57878482815481106113ab576113ab614dda565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790558782526008815260408083208a851680855292528083208054948d168452908320805463ffffffff90951663ffffffff199586161790559152805490911690556001915061142e565b8061142681614e1e565b91505061135a565b508061144d576040516305031d1160e31b815260040160405180910390fd5b604080518082018252600181524263ffffffff90811660208084019182526001600160a01b038c81166000818152600590935286832095518654945164ffffffffff1990951690151564ffffffff00191617610100949095169390930293909317909355908816808352838320805460ff1916905592519092917f05d866cd9c6000815d031b7ce30f30f643766eba16be13cff25924dc8ad8209291a350505050505050565b6006602052816000526040600020818154811061150f57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600061153660345490565b905090565b60008061154783612d53565b60008181526009602052604081205491925063ffffffff90911690819003610d795760405163d173577960e01b815260040160405180910390fd5b6000610cdf603483612eae565b6060610d7960328484612d81565b6000808215806115ae575060025483115b156115bf5750600192600092509050565b60008381526007602052604090206002600682015460ff1660078111156115e8576115e8614a17565b146115fa575060029360009350915050565b600054816003015461160c9190614e06565b421115611620575060039360009350915050565b6000848152600a60205260409020546003811061164557506004946000945092505050565b6000611652826003614e85565b935093505050915091565b6000806007600061166d85612ccd565b8152602080820192909252604090810160002081516101608101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b03811660a084015263ffffffff600160a01b8204811660c0850152600160c01b8204811660e0850152600160e01b90910416610100830152600681015461012083019060ff16600781111561171c5761171c614a17565b600781111561172d5761172d614a17565b815260200160078201805461174190614da6565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90614da6565b80156117ba5780601f1061178f576101008083540402835291602001916117ba565b820191906000526020600020905b81548152906001019060200180831161179d57829003601f168201915b5050505050815250509050600260078111156117d8576117d8614a17565b81610120015160078111156117ef576117ef614a17565b146117fd5750600092915050565b600054816060015161180f9190614e06565b42111561181f5750600092915050565b8060c0015163ffffffff168160e0015163ffffffff161015915050919050565b60006001600160a01b038216611868576040516342bcdf7f60e11b815260040160405180910390fd5b6036546040516001600160a01b038481166024830152600092839291169060440160408051601f198184030181529181526020820180516001600160e01b03166301fd3f7760e71b179052516118be9190614e9c565b600060405180830381855afa9150503d80600081146118f9576040519150601f19603f3d011682016040523d82523d6000602084013e6118fe565b606091505b5091509150816119615760405162461bcd60e51b8152602060048201526024808201527f476f76436f756e63696c3a206973417574686f72697a65642063616c6c2066616044820152631a5b195960e21b60648201526084015b60405180910390fd5b808060200190518101906119759190614eb8565b949350505050565b60008061198983612d53565b60009081526008602090815260408083206001600160a01b038816845290915290205463ffffffff16151591505092915050565b336000908152600560205260408120805460ff166119ee576040516305031d1160e31b815260040160405180910390fd5b60005b83811015611a5a57611a2b858583818110611a0e57611a0e614dda565b9050602002016020810190611a239190614b31565b603290612644565b611a48576040516326a5b9a160e21b815260040160405180910390fd5b80611a5281614e1e565b9150506119f1565b506110ae7fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed28585604051602001610c31929190614e37565b336000908152600560205260408120805460ff16611ac3576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b038316611aea576040516342bcdf7f60e11b815260040160405180910390fd5b611af5603484612644565b15611b13576040516301f0c0eb60e11b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee9101610c31565b80611b5c816128f3565b611b6882600180612f03565b5050565b336000908152600560205260408120805460ff16611b9d576040516305031d1160e31b815260040160405180910390fd5b6001805460009081526006602052604090205490819003611be4578363ffffffff16600114611bdf5760405163d173577960e01b815260040160405180910390fd5b611c1c565b60028463ffffffff161080611bfe5750808463ffffffff16115b15611c1c5760405163d173577960e01b815260040160405180910390fd5b6040805163ffffffff86166020820152600091016040516020818303038152906040529050611c6b7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b8261267e565b95945050505050565b336000908152600560205260408120805460ff16611ca5576040516305031d1160e31b815260040160405180910390fd5b6001831080611cb45750603283115b15611cd25760405163e46113f560e01b815260040160405180910390fd5b600083604051602001611ce791815260200190565b60405160208183030381529060405290506119757fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b588261267e565b6060611536603261331f565b6000610cdf603283612eae565b6060611536603461331f565b336000908152600560205260408120805460ff16611d78576040516305031d1160e31b815260040160405180910390fd5b6001600160a01b03841660009081526005602052604090205460ff16611db1576040516305031d1160e31b815260040160405180910390fd5b60018054600090815260066020526040902054908111611de45760405163d173577960e01b815260040160405180910390fd5b6000611df1600183614e85565b905080600103611e27578463ffffffff16600114611e225760405163d173577960e01b815260040160405180910390fd5b611e5f565b60028563ffffffff161080611e415750808563ffffffff16115b15611e5f5760405163d173577960e01b815260040160405180910390fd5b604080516001600160a01b038816602082015263ffffffff87168183015281518082038301815260609091019091526112517fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d8261267e565b611f176040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052906101208201908152602001606081525090565b611f2082612ccd565b60008181526007602081815260409283902083516101608101855281548152600182015492810192909252600281015493820193909352600383015460608201526004830154608082015260058301546001600160a01b03811660a083015263ffffffff600160a01b8204811660c0840152600160c01b8204811660e0840152600160e01b9091041661010082015260068301549395509261012084019160ff90911690811115611fd357611fd3614a17565b6007811115611fe457611fe4614a17565b8152602001600782018054611ff890614da6565b80601f016020809104026020016040519081016040528092919081815260200182805461202490614da6565b80156120715780601f1061204657610100808354040283529160200191612071565b820191906000526020600020905b81548152906001019060200180831161205457829003601f168201915b5050505050815250509050919050565b8061208b816128f3565b611b6882600080612f03565b336000908152600560205260408120805460ff166120c8576040516305031d1160e31b815260040160405180910390fd5b60005b838110156121685760008585838181106120e7576120e7614dda565b90506020020160208101906120fc9190614b31565b6001600160a01b031603612123576040516342bcdf7f60e11b815260040160405180910390fd5b612138858583818110611a0e57611a0e614dda565b1561215657604051632ada027560e21b815260040160405180910390fd5b8061216081614e1e565b9150506120cb565b506110ae7fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a08585604051602001610c31929190614e37565b336000908152600560205260408120805460ff166121d1576040516305031d1160e31b815260040160405180910390fd5b6121dc603484612644565b6121f9576040516305da0e2560e11b815260040160405180910390fd5b604080516001600160a01b0385166020820152610c45917f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e9101610c31565b80612242816128f3565b60008281526007602052604090206001600682015460ff16600781111561226b5761226b614a17565b14612289576040516377036cbb60e01b815260040160405180910390fd5b60058101546001600160a01b031633146122b657604051637d1b73b960e01b815260040160405180910390fd5b60058101546001600160c01b90910463ffffffff1611806122e757506005810154600160e01b900463ffffffff1615155b15612305576040516355fe710960e01b815260040160405180910390fd5b612310836004613385565b604051339084907f74c34a008ce735d9fcf0bd03a9b238d212ad4c441c020661f4ffbb6442645b8590600090a3505050565b336000908152600560205260408120805460ff16612373576040516305031d1160e31b815260040160405180910390fd5b60005b8381101561241357600085858381811061239257612392614dda565b90506020020160208101906123a79190614b31565b6001600160a01b0316036123ce576040516342bcdf7f60e11b815260040160405180910390fd5b6123e385858381811061102a5761102a614dda565b15612401576040516301f0c0eb60e11b815260040160405180910390fd5b8061240b81614e1e565b915050612376565b506110ae7f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a8585604051602001610c31929190614e37565b600081612457816128f3565b60008381526007602052604090206001600682015460ff16600781111561248057612480614a17565b141580156124a757506002600682015460ff1660078111156124a4576124a4614a17565b14155b156124b6576000925050610c48565b60005481600301546124c89190614e06565b42116124d8576000925050610c48565b6124e3846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a35060019392505050565b600061153660325490565b60006001600160a01b03821661254e576040516342bcdf7f60e11b815260040160405180910390fd5b6036546040516001600160a01b038481166024830152600092839291169060440160408051601f198184030181529181526020820180516001600160e01b031663fe575a8760e01b179052516125a49190614e9c565b600060405180830381855afa9150503d80600081146125df576040519150601f19603f3d011682016040523d82523d6000602084013e6125e4565b606091505b5091509150816119615760405162461bcd60e51b815260206004820152602560248201527f476f76436f756e63696c3a206973426c61636b6c69737465642063616c6c2066604482015264185a5b195960da1b6064820152608401611958565b60006001600160a01b03821661265c57506000610cdf565b506001600160a01b031660009081526001919091016020526040902054151590565b336000908152600560205260408120805460ff166126af576040516305031d1160e31b815260040160405180910390fd5b6000546000036126d2576040516387321fdd60e01b815260040160405180910390fd5b600c54336000908152600b6020526040902054106127035760405163090b564b60e01b815260040160405180910390fd5b60026000815461271290614e1e565b918290555060408051610160810182528681526001805460208301526000928201839052426060830152608082018390523360a083015260045463ffffffff1660c083015260e0820183905261010082019290925291935061012082019081526020908101859052600084815260078083526040918290208451815592840151600180850191909155918401516002840155606084015160038401556080840151600484015560a084015160058401805460c087015160e08801516101008901516001600160a01b039095166001600160c01b031990931692909217600160a01b63ffffffff92831602176001600160c01b0316600160c01b928216929092026001600160e01b031691909117600160e01b91909316029190911790556101208401516006840180549193909260ff1990921691849081111561285757612857614a17565b0217905550610140820151805161287891600784019160209091019061496e565b505060015460045460405133935085927f830652010a654c24b39890c16f53e6f6179becc61702ecd9a8c88461c2ff941a926128bf928a929163ffffffff16908a90614eda565b60405180910390a3336000908152600b602052604081208054916128e283614e1e565b91905055506110b182600180612f03565b60006007600061290284612ccd565b815260200190815260200160002090506000612922338360010154612cff565b60018301546000908152600660205260409020805491925090821061295a576040516305031d1160e31b815260040160405180910390fd5b336001600160a01b031681838154811061297657612976614dda565b6000918252602090912001546001600160a01b0316146129a9576040516305031d1160e31b815260040160405180910390fd5b50505050565b60006129b96133f5565b8215806129c7575060025483115b156129e557604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206002600682015460ff166007811115612a0e57612a0e614a17565b14612a2c57604051633c7e994560e11b815260040160405180910390fd5b600581015463ffffffff600160a01b82048116600160c01b909204161015612a6757604051638af69cf160e01b815260040160405180910390fd5b6000548160030154612a799190614e06565b421115612ac257612a8b846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a36000915050612cc3565b6000848152600a6020526040902054600311612b5957612ae3846006613385565b604080518082018252601781527f4d617820726574727920636f756e74207265616368656400000000000000000060208201529051339186917f68d5d5ea31f430b04112f5edc367c01af04da56d10cd663fbfbc4fbe5f509c2091612b4791614f0f565b60405180910390a36000915050612cc3565b6000848152600a60205260408120805491612b7383614e1e565b9190505550612c128160000154826007018054612b8f90614da6565b80601f0160208091040260200160405190810160405280929190818152602001828054612bbb90614da6565b8015612c085780601f10612bdd57610100808354040283529160200191612c08565b820191906000526020600020905b815481529060010190602001808311612beb57829003601f168201915b505050505061341f565b91508115612c6257612c25846003613385565b60405160018152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a3612cc1565b8215612c7857612c73846006613385565b612c88565b60068101805460ff191660021790555b60405160008152339085907f4fce71a6eb6a89b3e4c71722f870a263627cbfddc3a603c307803d89ad39e7cb9060200160405180910390a35b505b610cdf6000600355565b6000811580612cdd575060025482115b15612cfb57604051631dc0650160e31b815260040160405180910390fd5b5090565b60008181526008602090815260408083206001600160a01b038616845290915281205463ffffffff16808203612d3a57600019915050610cdf565b612d45600182614f22565b63ffffffff16949350505050565b6000811580612d63575060015482115b15612cfb576040516315ed869560e21b815260040160405180910390fd5b606082821015612da457604051634e23d03560e01b815260040160405180910390fd5b8354808310612dc657604051634e23d03560e01b815260040160405180910390fd5b6000612dd28585614e85565b612ddd906001614e06565b90508067ffffffffffffffff811115612df857612df8614f47565b604051908082528060200260200182016040528015612e21578160200160208202803683370190505b50925060005b81811015612ea45786612e3a8288614e06565b81548110612e4a57612e4a614dda565b9060005260206000200160009054906101000a90046001600160a01b0316848281518110612e7a57612e7a614dda565b6001600160a01b039092166020928302919091019091015280612e9c81614e1e565b915050612e27565b5050509392505050565b81546000908210612ed257604051634e23d03560e01b815260040160405180910390fd5b826000018281548110612ee757612ee7614dda565b6000918252602090912001546001600160a01b03169392505050565b821580612f11575060025483115b15612f2f57604051631dc0650160e31b815260040160405180910390fd5b60008381526007602052604090206001600682015460ff166007811115612f5857612f58614a17565b14158015612f7f57506002600682015460ff166007811115612f7c57612f7c614a17565b14155b15612f9d576040516377036cbb60e01b815260040160405180910390fd5b6000548160030154612faf9190614e06565b421115612ff457612fc1846005613385565b604051339085907fa07726147f0c03d4479e98c14466ffc4f275943ad74baa7e6bd84b99b02c80dc90600090a350505050565b600181015460006130053383612cff565b60008381526006602052604090208054919250908210613038576040516305031d1160e31b815260040160405180910390fd5b60ff82111561305a5760405163443afd7960e01b815260040160405180910390fd5b60028401546001831b908116156130845760405163080fc0bd60e11b815260040160405180910390fd5b6002850180548217905586156131e65760058501546000906130b490600160c01b900463ffffffff166001614f5d565b60058701805463ffffffff60c01b1916600160c01b63ffffffff848116918202929092179283905560408051600181526020810192909252600160e01b90930490911681830152905191925033918b917f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc05919081900360600190a3600586015463ffffffff600160a01b9091048116908216106131e0576002600687015460ff16600781111561316657613166614a17565b146131cd5760068601805460ff1916600217905560058601546040805163ffffffff8481168252600160e01b909304909216602083015233918b917f5064fb9bf50f615c47cc24c49119ba31d2c1a83ad6aed3b226cd42005524b7f4910160405180910390a35b86156131e0576131de8960006129af565b505b50613315565b600585015460009061320690600160e01b900463ffffffff166001614f5d565b6005870180546001600160e01b0316600160e01b63ffffffff84811691820292909217928390556040805160008152600160c01b90940490921660208401529082015290915033908a907f82b8cb75fd367be519fd5f57abcb2dbb773381c00082e94059c4713c4dfdfc059060600160405180910390a36005860154835460009161329f91600160a01b90910463ffffffff1690614f22565b90508063ffffffff168263ffffffff161115613312576132c08a6007613385565b60058701546040805163ffffffff600160c01b90930483168152918416602083015233918c917f6fa60fd92b2557298bb7b39e7b538b3f00ebf09b9f056bdeac7f0e5d57e8fcbb910160405180910390a35b50505b5050505050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561337957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161335b575b50505050509050919050565b60008281526007602081905260409091206006018054839260ff199091169060019084908111156133b8576133b8614a17565b021790555060038160078111156133d1576133d1614a17565b036133ec576000828152600760205260409020426004909101555b611b6882613568565b600354600103613418576040516306fda65d60e31b815260040160405180910390fd5b6001600355565b60007fb8a139bd0f2c391603a08ccf44ed2063b179fe3c3ce0aa566d079d6b67c7bfbb8303613478576000808380602001905181019061345f9190614f85565b9150915061346d82826135c7565b600192505050610cdf565b7fa9e62343bdcc3c1dce78187df134d12ecb689f736a336f163fbc89da1105164d83036134c457600080838060200190518101906134b69190614f85565b9150915061346d828261390f565b7ff292dae4f7fef5771b34a5c5c053f8948dafc6fe09549ca1dc8a315bc893568b8303613516576000828060200190518101906135019190614fb4565b905061350c81613bc7565b6001915050610cdf565b7fc2a205f073088e79f5bd01c0575abfe4dc2f5a22197da4f2392a96f38aad4b58830361355e576000828060200190518101906135539190614fd1565b905061350c81613cca565b610d798383613d3c565b6000818152600760209081526040808320600501546001600160a01b0316808452600b9092529091205415611b68576001600160a01b0381166000908152600b602052604081208054916135bb83614fea565b91905055505050565b50565b6001600160a01b03821660009081526005602052604090205460ff16156136015760405163a929afd160e01b815260040160405180910390fd5b6001600160a01b0382166136285760405163ddf1d6dd60e01b815260040160405180910390fd5b6000806000613635614089565b81549295509093509150600061364c826001614e06565b905060ff821061366f5760405163443afd7960e01b815260040160405180910390fd5b806001036136a3578563ffffffff1660011461369e5760405163d173577960e01b815260040160405180910390fd5b6136db565b60028663ffffffff1610806136bd5750808663ffffffff16115b156136db5760405163d173577960e01b815260040160405180910390fd5b60005b828110156137945760008582815481106136fa576136fa614dda565b6000918252602080832090910154895460018181018c558b85529290932090920180546001600160a01b0319166001600160a01b039093169283179055909150613745908390614e06565b60008681526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff9092169190911790558061378c81614e1e565b9150506136de565b5084546001808201875560008781526020902090910180546001600160a01b0319166001600160a01b038a161790556137ce908390614e06565b60008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff1990811663ffffffff978816179091558251808401845260018152428716818601908152838752600586529584902090518154965164ffffffffff1990971690151564ffffffff001916176101009688169690960295909517909455600480549485168c87169081179091558a5483519081529384015292909316927fd693483bf3059d721fcb091390377153e45c1b15c85015ea8c5547b92960ff56910160405180910390a26040805163ffffffff8084168252891660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a15050506000908152600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b6001600160a01b03821660009081526005602052604090205460ff16613948576040516305031d1160e31b815260040160405180910390fd5b6000806000613955614089565b81549295509093509150600061396c600183614e85565b90508060000361398f5760405163d173577960e01b815260040160405180910390fd5b806001036139c3578563ffffffff166001146139be5760405163d173577960e01b815260040160405180910390fd5b6139fb565b60028663ffffffff1610806139dd5750808663ffffffff16115b156139fb5760405163d173577960e01b815260040160405180910390fd5b6000805b83811015613ac4576000868281548110613a1b57613a1b614dda565b6000918252602090912001546001600160a01b0390811691508a168103613a425750613ab2565b87546001810189556000898152602090200180546001600160a01b0319166001600160a01b038316179055613a7683614e1e565b60008781526008602090815260408083206001600160a01b0395909516835293905291909120805463ffffffff191663ffffffff831617905591505b80613abc81614e1e565b9150506139ff565b5060008481526008602090815260408083206001600160a01b038c16808552908352818420805463ffffffff199081169091556005845293829020805460ff191690556004805494851663ffffffff8d81169182179092558b5484519081529485015290931692917fab15a70783712986077aea9a4cbfd4c1561dd8672489037c581fbaf8fc658516910160405180910390a26040805163ffffffff80841682528a1660208201527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a1505050600091825250600960205260409020805463ffffffff191663ffffffff9490941693909317909255505050565b6001805460009081526006602052604090205490819003613c0e578163ffffffff16600114613c095760405163d173577960e01b815260040160405180910390fd5b613c46565b60028263ffffffff161080613c285750808263ffffffff16115b15613c465760405163d173577960e01b815260040160405180910390fd5b6004805463ffffffff84811663ffffffff1983168117909355604080519190921680825260208201939093527f6b25ecb86b78350c27ff9ed279ad8aec3f418d60a233cdcab2bddb8713e10c5f910160405180910390a150506001546000908152600960205260409020805463ffffffff191663ffffffff92909216919091179055565b6001811080613cd95750603281115b15613cf75760405163e46113f560e01b815260040160405180910390fd5b600c80549082905560408051828152602081018490527f56b9de3a8fc94721b6e3f917d89308667325aefa7d3d6d99b42acda37f3855bf910160405180910390a15050565b60007f3e9e5ed42b9098e49a88e5f4bd3da741a16df05606fabaeb48638dfd1d42f02b8303613d9157600082806020019051810190613d7b9190615001565b9050613d89816002546140c4565b915050610cdf565b7fa637fdd99bb7e7098b6dddecd11b0322d125fcf0c14db796406d24d1ddd3a2a08303613e1f57600082806020019051810190613dce919061502e565b905060005b8151811015613e1457613e01828281518110613df157613df1614dda565b60200260200101516002546140c4565b5080613e0c81614e1e565b915050613dd3565b506001915050610cdf565b7f267c40d522f8e06512003bfd4a134508bc508db468975c39e0f0ef7209389ac38303613e6a57600082806020019051810190613e5c9190615001565b9050613d8981600254614292565b7fb022ce27ef6cc2fe0ad17be7d7e5920364df4deb3aef30cacca59d735f504ed28303613eed57600082806020019051810190613ea7919061502e565b905060005b8151811015613e1457613eda828281518110613eca57613eca614dda565b6020026020010151600254614292565b5080613ee581614e1e565b915050613eac565b7ffa53135c5eb56c84d712ef30bdf44f92bdc2fc0aad6b94b92682caf15131bdee8303613f3857600082806020019051810190613f2a9190615001565b9050613d898160025461443c565b7f2e2aff63a1c3b237c2e6ff0982d1ce852f1a5af67c62e0eb3039bf4e6c41036a8303613fbb57600082806020019051810190613f75919061502e565b905060005b8151811015613e1457613fa8828281518110613f9857613f98614dda565b602002602001015160025461443c565b5080613fb381614e1e565b915050613f7a565b7f01fcb42fb40ab90b2977cac9638c5727bf2cd5b757ca529471edc46431cfa56e830361400657600082806020019051810190613ff89190615001565b9050613d89816002546145e7565b7fa00e5d8087bfc9c377f0ac5437b4609e8cbbc76b65f0ab8b79bd53735060428b8303610f3857600082806020019051810190614043919061502e565b905060005b8151811015613e145761407682828151811061406657614066614dda565b60200260200101516002546145e7565b508061408181614e1e565b915050614048565b60008060008060015490508060016140a19190614e06565b600091825260066020526040808320828452922060018290559591945092509050565b60006140d1603284612644565b156141345781836001600160a01b031660008051602061510a833981519152604051614124906020808252601390820152721053149150511657d0931050d2d31254d51151606a1b604082015260600190565b60405180910390a3506000610cdf565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316633e7e4af960e21b179052516141879190614e9c565b6000604051808303816000865af19150503d80600081146141c4576040519150601f19603f3d011682016040523d82523d6000602084013e6141c9565b606091505b50509050806142465782846001600160a01b031660008051602061510a8339815191526040516142349060208082526021908201527f476f76436f756e63696c3a20626c61636b6c6973742063616c6c206661696c656040820152601960fa1b606082015260800190565b60405180910390a36000915050610cdf565b61425160328561478f565b5060405183906001600160a01b038616907f1d2c7e6b911a4ad6c07d780ccd7e533749bff42c2b1d161c21f3fc7c830eb2cc90600090a35060019392505050565b600061429f603284612644565b6142ee5781836001600160a01b031660008051602061510a8339815191526040516141249060208082526010908201526f1393d517d25397d0931050d2d31254d560821b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316630d44a93360e11b179052516143419190614e9c565b6000604051808303816000865af19150503d806000811461437e576040519150601f19603f3d011682016040523d82523d6000602084013e614383565b606091505b50509050806143f05782846001600160a01b031660008051602061510a8339815191526040516142349060208082526023908201527f476f76436f756e63696c3a20756e426c61636b6c6973742063616c6c206661696040820152621b195960ea1b606082015260800190565b6143fb603285614828565b5060405183906001600160a01b038616907f5428c9b1fb7549fe41c6846061bfb4c682760e630052c3d880669ece73427cb790600090a35060019392505050565b6000614449603484612644565b1561449b5781836001600160a01b031660008051602061510a833981519152604051614124906020808252601290820152711053149150511657d055551213d49256915160721b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316635b52ebef60e11b179052516144ee9190614e9c565b6000604051808303816000865af19150503d806000811461452b576040519150601f19603f3d011682016040523d82523d6000602084013e614530565b606091505b505090508061459b5782846001600160a01b031660008051602061510a8339815191526040516142349060208082526021908201527f476f76436f756e63696c3a20617574686f72697a652063616c6c206661696c656040820152601960fa1b606082015260800190565b6145a660348561478f565b5060405183906001600160a01b038616907f3110d1ee06428a72c2523738b03b74d2cac172112945536944ef0d34f917594790600090a35060019392505050565b60006145f4603484612644565b6146415781836001600160a01b031660008051602061510a833981519152604051614124906020808252600e908201526d1393d517d055551213d49256915160921b604082015260600190565b6036546040516001600160a01b038581166024830152600092169060440160408051601f198184030181529181526020820180516001600160e01b0316633bbbc7c960e01b179052516146949190614e9c565b6000604051808303816000865af19150503d80600081146146d1576040519150601f19603f3d011682016040523d82523d6000602084013e6146d6565b606091505b50509050806147435782846001600160a01b031660008051602061510a8339815191526040516142349060208082526023908201527f476f76436f756e63696c3a20756e417574686f72697a652063616c6c206661696040820152621b195960ea1b606082015260800190565b61474e603485614828565b5060405183906001600160a01b038616907f50481a3a74ecdf57138218d3d03198c96d338a47f85893e68628c4689d71534790600090a35060019392505050565b60006001600160a01b0382166147b8576040516342bcdf7f60e11b815260040160405180910390fd5b6147c28383612644565b156147e05760405163516c350f60e11b815260040160405180910390fd5b508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03959095169485179055845493815293810190915260409092205590565b6001600160a01b038116600090815260018301602052604081205480820361486357604051636054b46960e01b815260040160405180910390fd5b6000614870600183614e85565b855490915060009061488490600190614e85565b90508082146149105760008660000182815481106148a4576148a4614dda565b60009182526020909120015487546001600160a01b03909116915081908890859081106148d3576148d3614dda565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815260018801909152604090208390555b8554869080614921576149216150f3565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825260018881019091526040822091909155935050505092915050565b82805461497a90614da6565b90600052602060002090601f01602090048101928261499c57600085556149e2565b82601f106149b557805160ff19168380011785556149e2565b828001600101855582156149e2579182015b828111156149e25782518255916020019190600101906149c7565b50612cfb9291505b80821115612cfb57600081556001016149ea565b600060208284031215614a1057600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60088110614a3d57614a3d614a17565b9052565b60005b83811015614a5c578181015183820152602001614a44565b838111156129a95750506000910152565b60008151808452614a85816020860160208601614a41565b601f01601f19169290920160200192915050565b8b8152602081018b9052604081018a905260608101899052608081018890526001600160a01b03871660a082015263ffffffff86811660c083015285811660e083015284166101008201526000610160614af7610120840186614a2d565b80610140840152614b0a81840185614a6d565b9e9d5050505050505050505050505050565b6001600160a01b03811681146135c457600080fd5b600060208284031215614b4357600080fd5b8135610d7981614b1c565b60008060408385031215614b6157600080fd5b8235614b6c81614b1c565b946020939093013593505050565b60008060408385031215614b8d57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015614bdd5783516001600160a01b031683529284019291840191600101614bb8565b50909695505050505050565b60008060208385031215614bfc57600080fd5b823567ffffffffffffffff80821115614c1457600080fd5b818501915085601f830112614c2857600080fd5b813581811115614c3757600080fd5b8660208260051b8501011115614c4c57600080fd5b60209290920196919550909350505050565b63ffffffff811681146135c457600080fd5b60008060408385031215614c8357600080fd5b8235614c8e81614b1c565b91506020830135614c9e81614c5e565b809150509250929050565b6040810160058410614cbd57614cbd614a17565b9281526020015290565b600060208284031215614cd957600080fd5b8135610d7981614c5e565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a0830151614d3360c08401826001600160a01b03169052565b5060c083015163ffffffff811660e08401525060e0830151610100614d5f8185018363ffffffff169052565b8401519050610120614d788482018363ffffffff169052565b8401519050610140614d8c84820183614a2d565b8401516101608481015290506110ae610180840182614a6d565b600181811c90821680614dba57607f821691505b602082108103610c4857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115614e1957614e19614df0565b500190565b600060018201614e3057614e30614df0565b5060010190565b60208082528181018390526000908460408401835b86811015614e7a578235614e5f81614b1c565b6001600160a01b031682529183019190830190600101614e4c565b509695505050505050565b600082821015614e9757614e97614df0565b500390565b60008251614eae818460208701614a41565b9190910192915050565b600060208284031215614eca57600080fd5b81518015158114610d7957600080fd5b84815283602082015263ffffffff83166040820152608060608201526000614f056080830184614a6d565b9695505050505050565b602081526000610d796020830184614a6d565b600063ffffffff83811690831681811015614f3f57614f3f614df0565b039392505050565b634e487b7160e01b600052604160045260246000fd5b600063ffffffff808316818516808303821115614f7c57614f7c614df0565b01949350505050565b60008060408385031215614f9857600080fd5b8251614fa381614b1c565b6020840151909250614c9e81614c5e565b600060208284031215614fc657600080fd5b8151610d7981614c5e565b600060208284031215614fe357600080fd5b5051919050565b600081614ff957614ff9614df0565b506000190190565b60006020828403121561501357600080fd5b8151610d7981614b1c565b805161502981614b1c565b919050565b6000602080838503121561504157600080fd5b825167ffffffffffffffff8082111561505957600080fd5b818501915085601f83011261506d57600080fd5b81518181111561507f5761507f614f47565b8060051b604051601f19603f830116810181811085821117156150a4576150a4614f47565b6040529182528482019250838101850191888311156150c257600080fd5b938501935b828510156150e7576150d88561501e565b845293850193928501926150c7565b98975050505050505050565b634e487b7160e01b600052603160045260246000fdfe5ec90e8f4a61404dd1a1a05fdde3f3ce998aaaf78e579739308751e16300734ea2646970667358221220c9ab53da82cc7ef5444ec14b756ade7ca555d020df1fab2620cf0055fd893ae464736f6c634300080e0033", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "093a80", - "0x0000000000000000000000000000000000000000000000000000000000000001": "01", - "0x0000000000000000000000000000000000000000000000000000000000000004": "01", "0x000000000000000000000000000000000000000000000000000000000000000c": "03", - "0x0000000000000000000000000000000000000000000000000000000000000036": "b00003", - "0x3133b9fb7810b2a7f735819914587f60831e339d00b86c5bf810f9f39090fd99": "01", - "0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31": "01", - "0x51dc2ffa66476bb8bdfa05ea53597330d344ad85930a2281ddb9910f878716a1": "01", - "0x80497882cf9008f7f796a89e5514a7b55bd96eab88ecb66aee4fb0a6fd34811c": "aa5faa65e9cc0f74a85b6fdfb5f6991f5c094697", - "0x92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36": "01" + "0x0000000000000000000000000000000000000000000000000000000000000036": "b00003" }, "address": "0x0000000000000000000000000000000000001004", "key": "0xb8683e1d755c8cf95151c1e8809332cb56c747579c66fec109eb1de472d163fe" @@ -175,7 +167,7 @@ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "address": "0x08d3b23dbfe8ef7965a8b5e4d9c21feddbc11491", - "key": "0x792cc9f20a61c16646d5b6136693e7789549adb7d8e35503d0004130ea6528b0" + "key": "0x7963685967117ffb6fd019663dc9e782ebb1234a38501bffc2eb5380f8dc303b" }, "0x09B9C1875399CD724B1017F155A193713Cb23732": { "balance": "0", @@ -672,6 +664,14 @@ "address": "0x4340ee1b812acb40a1eb561c019c327b243b92df", "key": "0xa13bfef92e05edee891599aa5e447ff2baa1708d9a6473a04ef66ab94f2a11e4" }, + "0x45dFD9F6dA52AbaeE54AD49226c698e45b2f3777": { + "balance": "1000000000000000141225925000028245185", + "nonce": 0, + "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "address": "0x45dfd9f6da52abaee54ad49226c698e45b2f3777", + "key": "0xc059d84d208470651f74401b7d33a9cd614416571490320410c15f2faaaffd5c" + }, "0x46bFe8155134dcD7bB9baDEf1B2EF25AE86435C8": { "balance": "0", "nonce": 1, @@ -1316,14 +1316,6 @@ "address": "0x7dcd17433742f4c0ca53122ab541d0ba67fc27df", "key": "0xbf1f52c702c40589735c4b038bd94e04268a58c35afad63bb16c071d62d2e23d" }, - "0x7a2B5390bb632269133D3B7Eda466b4b44bf2762": { - "balance": "1000000000000000141225925000028245185", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "address": "0x7a2b5390bb632269133d3b7eda466b4b44bf2762", - "key": "0x0094d0d9e7b60647eb372835f53745d85577ee01ff52be50d16ade8644ea1c02" - }, "0x7fd02A3bB5D5926d4981eFBF63b66DE2a7b1aA63": { "balance": "0", "nonce": 1, diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 9ba93d05f..e387b4f9b 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -206,7 +206,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg}) continue } - msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee, nil) + msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee, nil, statedb) if err != nil { log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) @@ -284,6 +284,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, //receipt.BlockHash //receipt.BlockNumber receipt.TransactionIndex = uint(txIndex) + + if chainConfig.AnzeonEnabled() { + receipt.EffectiveGasPrice = msg.GasPrice + } + receipts = append(receipts, receipt) } diff --git a/core/blockchain.go b/core/blockchain.go index 767dcc074..d4e077b75 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2115,12 +2115,7 @@ func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { } receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64()) - var headerGasTip *big.Int - if b.Header() != nil && b.Header().GasTip() != nil { - headerGasTip = b.Header().GasTip() - } - - if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), headerGasTip, blobGasPrice, b.Transactions()); err != nil { + if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil { log.Error("Failed to derive block receipts fields", "hash", b.Hash(), "number", b.NumberU64(), "err", err) } var logs []*types.Log diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index b16fa2b82..2642700b7 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -227,6 +227,7 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { if header == nil { return nil } + receipts := rawdb.ReadReceipts(bc.db, hash, *number, header.Time, bc.chainConfig) if receipts == nil { return nil diff --git a/core/chain_makers.go b/core/chain_makers.go index da594b9dd..1cfae2fb4 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -409,12 +409,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas()) } - var headerGasTip *big.Int - if block.Header() != nil && block.Header().GasTip() != nil { - headerGasTip = block.Header().GasTip() - } - - if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), headerGasTip, blobGasPrice, txs); err != nil { + if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil { panic(err) } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 93546b75d..187ffd15f 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -35,6 +35,10 @@ import ( "golang.org/x/exp/slices" ) +// StateReader is an alias for types.StateReader to maintain backward compatibility. +// The interface is defined in types package to avoid circular dependencies. +type StateReader = types.StateReader + // ReadCanonicalHash retrieves the hash assigned to a canonical block number. func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { var data []byte @@ -649,12 +653,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64, blobGasPrice = eip4844.CalcBlobFee(*header.ExcessBlobGas) } - var headerGasTip *big.Int - if header != nil && header.GasTip() != nil { - headerGasTip = new(big.Int).Set(header.GasTip()) - } - - if err := receipts.DeriveFields(config, hash, number, time, baseFee, headerGasTip, blobGasPrice, body.Transactions); err != nil { + if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil { log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) return nil } @@ -692,6 +691,7 @@ type storedReceiptRLP struct { PostStateOrStatus []byte CumulativeGasUsed uint64 Logs []*types.Log + EffectiveGasPrice *big.Int `rlp:"optional"` } // ReceiptLogs is a barebone version of ReceiptForStorage which only keeps diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index a7ceb7299..ba3d099aa 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -357,9 +357,10 @@ func TestBlockReceiptStorage(t *testing.T) { {Address: common.BytesToAddress([]byte{0x11})}, {Address: common.BytesToAddress([]byte{0x01, 0x11})}, }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, + EffectiveGasPrice: big.NewInt(10000000000000), + TxHash: tx1.Hash(), + ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), + GasUsed: 111111, } receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) @@ -370,9 +371,10 @@ func TestBlockReceiptStorage(t *testing.T) { {Address: common.BytesToAddress([]byte{0x22})}, {Address: common.BytesToAddress([]byte{0x02, 0x22})}, }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, + EffectiveGasPrice: big.NewInt(10000000000000), + TxHash: tx2.Hash(), + ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), + GasUsed: 222222, } receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipts := []*types.Receipt{receipt1, receipt2} @@ -705,9 +707,10 @@ func TestReadLogs(t *testing.T) { {Address: common.BytesToAddress([]byte{0x11})}, {Address: common.BytesToAddress([]byte{0x01, 0x11})}, }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, + TxHash: tx1.Hash(), + ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), + EffectiveGasPrice: big.NewInt(10000000000000), + GasUsed: 111111, } receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) @@ -718,9 +721,10 @@ func TestReadLogs(t *testing.T) { {Address: common.BytesToAddress([]byte{0x22})}, {Address: common.BytesToAddress([]byte{0x02, 0x22})}, }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, + TxHash: tx2.Hash(), + ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), + EffectiveGasPrice: big.NewInt(10000000000000), + GasUsed: 222222, } receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipts := []*types.Receipt{receipt1, receipt2} diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 5c84e3190..ec1899abb 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -64,7 +64,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c } // Convert the transaction into an executable message and pre-cache its sender - msg, err := TransactionToMessage(tx, signer, header.BaseFee, header.GasTip()) + msg, err := TransactionToMessage(tx, signer, header.BaseFee, header.GasTip(), statedb) if err != nil { return // Also invalid block, bail out } diff --git a/core/state_processor.go b/core/state_processor.go index 0ceaf49c3..44d11e144 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -81,7 +81,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { - msg, err := TransactionToMessage(tx, signer, header.BaseFee, header.GasTip()) + msg, err := TransactionToMessage(tx, signer, header.BaseFee, header.GasTip(), statedb) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -153,6 +153,10 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta receipt.BlockHash = blockHash receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) + + if config.AnzeonEnabled() { + receipt.EffectiveGasPrice = msg.GasPrice + } return receipt, err } @@ -161,7 +165,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { - msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee, header.GasTip()) + msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee, header.GasTip(), statedb) if err != nil { return nil, err } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 276a1c321..b07b4d4b5 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -20,6 +20,7 @@ import ( "crypto/ecdsa" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -29,10 +30,12 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" @@ -422,3 +425,409 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr } return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) } + +var ( + // Test accounts + testTxMsgAuthorizedKey, _ = crypto.GenerateKey() + testTxMsgAuthorizedAddr = crypto.PubkeyToAddress(testTxMsgAuthorizedKey.PublicKey) + + testTxMsgNormalKey, _ = crypto.GenerateKey() + testTxMsgNormalAddr = crypto.PubkeyToAddress(testTxMsgNormalKey.PublicKey) +) + +// setupTestStateDB creates a stateDB for testing. +func setupTestStateDB() *state.StateDB { + // Create stateDB for testing (prepared for future StateAccount.Extra field usage) + db := rawdb.NewMemoryDatabase() + sdb := state.NewDatabase(db) + stateDB, _ := state.New(types.EmptyRootHash, sdb, nil) + + // Include all test accounts in stateDB + allAddrs := []common.Address{ + testTxMsgAuthorizedAddr, + testTxMsgNormalAddr, + } + for _, addr := range allAddrs { + stateDB.CreateAccount(addr) + } + + if stateDB != nil { + stateDB.SetAuthorized(testTxMsgAuthorizedAddr) + } + + return stateDB +} + +// TestTransactionToMessageAuthorizedAccount tests that authorized accounts use their transaction's GasTipCap +func TestTransactionToMessageAuthorizedAccount(t *testing.T) { + t.Parallel() + + stateDB := setupTestStateDB() + signer := types.LatestSignerForChainID(common.Big1) + + // Test parameters + baseFee := big.NewInt(10) + headerGasTip := big.NewInt(5) + txGasTipCap := big.NewInt(20) // Authorized account's gas tip cap (higher than headerGasTip) + txGasFeeCap := big.NewInt(50) + + // Create transaction from authorized account + tx, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 21000, + GasTipCap: txGasTipCap, + GasFeeCap: txGasFeeCap, + Data: nil, + }), signer, testTxMsgAuthorizedKey) + if err != nil { + t.Fatalf("failed to sign transaction: %v", err) + } + + // Convert transaction to message + msg, err := TransactionToMessage(tx, signer, baseFee, headerGasTip, stateDB) + if err != nil { + t.Fatalf("failed to convert transaction to message: %v", err) + } + + // Verify that authorized account uses transaction's GasTipCap + expectedGasTipCap := txGasTipCap + if msg.GasTipCap.Cmp(expectedGasTipCap) != 0 { + t.Errorf("expected GasTipCap %v, got %v", expectedGasTipCap, msg.GasTipCap) + } +} + +// TestTransactionToMessageNormalAccount tests that normal accounts use header's gas tip +func TestTransactionToMessageNormalAccount(t *testing.T) { + t.Parallel() + + stateDB := setupTestStateDB() + signer := types.LatestSignerForChainID(common.Big1) + + // Test parameters + baseFee := big.NewInt(10) + headerGasTip := big.NewInt(5) + txGasTipCap := big.NewInt(20) // Normal account's gas tip cap (higher than headerGasTip, but should be ignored) + txGasFeeCap := big.NewInt(50) + + // Create transaction from normal account + tx, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 21000, + GasTipCap: txGasTipCap, + GasFeeCap: txGasFeeCap, + Data: nil, + }), signer, testTxMsgNormalKey) + if err != nil { + t.Fatalf("failed to sign transaction: %v", err) + } + + // Convert transaction to message + msg, err := TransactionToMessage(tx, signer, baseFee, headerGasTip, stateDB) + if err != nil { + t.Fatalf("failed to convert transaction to message: %v", err) + } + + // Verify that normal account uses header's gas tip (not transaction's GasTipCap) + expectedGasTipCap := headerGasTip + if msg.GasTipCap.Cmp(expectedGasTipCap) != 0 { + t.Errorf("expected GasTipCap %v (headerGasTip), got %v (tx.GasTipCap was %v but should be ignored)", + expectedGasTipCap, msg.GasTipCap, txGasTipCap) + } +} + +// TestApplyTransactionAuthorizedAccount tests that authorized accounts pay actual gas fee based on their transaction's GasTipCap +func TestApplyTransactionAuthorizedAccount(t *testing.T) { + t.Parallel() + + stateDB := setupTestStateDB() + signer := types.LatestSignerForChainID(common.Big1) + + // Set up account balance for gas payment (enough for gas fee) + stateDB.AddBalance(testTxMsgAuthorizedAddr, uint256.MustFromBig(big.NewInt(10000000))) + + // Test parameters + baseFee := big.NewInt(100) + headerGasTip := big.NewInt(10) // Set the gas tip we want to test + txGasTipCap := big.NewInt(50) // Authorized account's gas tip cap (higher than headerGasTip) + txGasFeeCap := big.NewInt(200) + + // Create transaction from authorized account + tx, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: txGasTipCap, + GasFeeCap: txGasFeeCap, + Data: nil, + }), signer, testTxMsgAuthorizedKey) + if err != nil { + t.Fatalf("failed to sign transaction: %v", err) + } + + // Create test header + header := &types.Header{ + Number: big.NewInt(1), + Time: uint64(time.Now().Unix()), + BaseFee: baseFee, + GasLimit: 30000000, + GasUsed: 0, + Coinbase: common.Address{}, + ParentHash: common.Hash{}, + Root: common.Hash{}, + TxHash: common.Hash{}, + ReceiptHash: common.Hash{}, + UncleHash: common.Hash{}, + Difficulty: big.NewInt(0), + } + + // Set up WBFTExtra in header.Extra for Anzeon + wbftExtra := &types.WBFTExtra{ + VanityData: make([]byte, types.IstanbulExtraVanity), + RandaoReveal: []byte{}, + PrevRound: 0, + PrevPreparedSeal: nil, + PrevCommittedSeal: nil, + Round: 0, + PreparedSeal: nil, + CommittedSeal: nil, + GasTip: new(big.Int).Set(headerGasTip), + EpochInfo: nil, + } + extraData, err := rlp.EncodeToBytes(wbftExtra) + if err != nil { + t.Fatalf("failed to encode WBFTExtra: %v", err) + } + header.Extra = extraData + + // Create chain config + config := ¶ms.ChainConfig{ + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Anzeon: ¶ms.AnzeonConfig{ + SystemContracts: ¶ms.SystemContracts{ + NativeCoinAdapter: ¶ms.SystemContract{ + Address: params.DefaultNativeCoinAdapterAddress, + Version: params.DefaultNativeCoinAdapterVersion, + }, + }, + }, + } + + // Apply transaction + coinbase := common.Address{0x1} // Use a non-zero address for coinbase + gp := new(GasPool).AddGas(header.GasLimit) + usedGas := uint64(0) + receipt, err := ApplyTransaction(config, nil, &coinbase, gp, stateDB, header, tx, &usedGas, vm.Config{}) + if err != nil { + t.Fatalf("failed to apply transaction: %v", err) + } + + // Verify receipt status + if receipt.Status != types.ReceiptStatusSuccessful { + t.Errorf("expected transaction to succeed, got status %d", receipt.Status) + } + + msg, err := TransactionToMessage(tx, signer, baseFee, headerGasTip, stateDB) + if err != nil { + t.Fatalf("failed to convert transaction to message: %v", err) + } + + // Verify that authorized account uses transaction's GasTipCap + if msg.GasTipCap.Cmp(txGasTipCap) != 0 { + t.Errorf("expected GasTipCap %v, got %v", txGasTipCap, msg.GasTipCap) + } + + // Calculate expected effective gas price for authorized account + // Authorized account uses tx.GasTipCap, so effectiveGasPrice = baseFee + txGasTipCap + expectedEffectiveGasPrice := new(big.Int).Add(baseFee, txGasTipCap) + if txGasFeeCap.Cmp(expectedEffectiveGasPrice) < 0 { + t.Errorf("txGasFeeCap is less than expectedEffectiveGasPrice") + } + + anzeonGasTip := types.NewInstantAnzeonTipEnv(signer, baseFee, headerGasTip, stateDB) + actualEffectiveGasPrice, _ := tx.EffectiveGasTip(anzeonGasTip) + if actualEffectiveGasPrice == nil { + t.Errorf("actualEffectiveGasPrice is nil") + } + actualEffectiveGasPrice = actualEffectiveGasPrice.Add(actualEffectiveGasPrice, baseFee) + + // Verify effective gas price matches expected value + if actualEffectiveGasPrice.Cmp(expectedEffectiveGasPrice) != 0 { + t.Errorf("expected effective gas price %v (baseFee %v + GasTipCap %v, capped by GasFeeCap %v), got %v", + expectedEffectiveGasPrice, baseFee, txGasTipCap, txGasFeeCap, actualEffectiveGasPrice) + } + + // Calculate and verify total gas fee paid + expectedTotalGasFee := new(big.Int).Mul(big.NewInt(int64(receipt.GasUsed)), expectedEffectiveGasPrice) + actualTotalGasFee := new(big.Int).Mul(big.NewInt(int64(receipt.GasUsed)), actualEffectiveGasPrice) + + if actualTotalGasFee.Cmp(expectedTotalGasFee) != 0 { + t.Errorf("expected total gas fee %v (GasUsed %d * effectiveGasPrice %v), got %v", + expectedTotalGasFee, receipt.GasUsed, expectedEffectiveGasPrice, actualTotalGasFee) + } + + t.Logf("Authorized account - GasUsed: %d, EffectiveGasPrice: %v, TotalGasFee: %v", + receipt.GasUsed, actualEffectiveGasPrice, actualTotalGasFee) +} + +// TestApplyTransactionNormalAccount tests that normal accounts pay actual gas fee based on header's gas tip +func TestApplyTransactionNormalAccount(t *testing.T) { + t.Parallel() + + stateDB := setupTestStateDB() + signer := types.LatestSignerForChainID(common.Big1) + + // Set up account balance for gas payment (enough for gas fee) + stateDB.AddBalance(testTxMsgNormalAddr, uint256.MustFromBig(big.NewInt(10000000))) + + // Test parameters + baseFee := big.NewInt(100) + headerGasTip := big.NewInt(10) // Set the gas tip we want to test + txGasTipCap := big.NewInt(50) // Normal account's gas tip cap (higher than headerGasTip, but should be ignored) + txGasFeeCap := big.NewInt(200) + + // Create transaction from normal account + tx, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(0), + Gas: 21000, + GasTipCap: txGasTipCap, + GasFeeCap: txGasFeeCap, + Data: nil, + }), signer, testTxMsgNormalKey) + if err != nil { + t.Fatalf("failed to sign transaction: %v", err) + } + + // Create test header + header := &types.Header{ + Number: big.NewInt(1), + Time: uint64(time.Now().Unix()), + BaseFee: baseFee, + GasLimit: 30000000, + GasUsed: 0, + Coinbase: common.Address{}, + ParentHash: common.Hash{}, + Root: common.Hash{}, + TxHash: common.Hash{}, + ReceiptHash: common.Hash{}, + UncleHash: common.Hash{}, + Difficulty: big.NewInt(0), + } + + // Set up WBFTExtra in header.Extra for Anzeon + wbftExtra := &types.WBFTExtra{ + VanityData: make([]byte, types.IstanbulExtraVanity), + RandaoReveal: []byte{}, + PrevRound: 0, + PrevPreparedSeal: nil, + PrevCommittedSeal: nil, + Round: 0, + PreparedSeal: nil, + CommittedSeal: nil, + GasTip: new(big.Int).Set(headerGasTip), + EpochInfo: nil, + } + extraData, err := rlp.EncodeToBytes(wbftExtra) + if err != nil { + t.Fatalf("failed to encode WBFTExtra: %v", err) + } + header.Extra = extraData + + // Create chain config + config := ¶ms.ChainConfig{ + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Anzeon: ¶ms.AnzeonConfig{ + SystemContracts: ¶ms.SystemContracts{ + NativeCoinAdapter: ¶ms.SystemContract{ + Address: params.DefaultNativeCoinAdapterAddress, + Version: params.DefaultNativeCoinAdapterVersion, + }, + }, + }, + } + + // Apply transaction + coinbase := common.Address{0x1} // Use a non-zero address for coinbase + gp := new(GasPool).AddGas(header.GasLimit) + usedGas := uint64(0) + receipt, err := ApplyTransaction(config, nil, &coinbase, gp, stateDB, header, tx, &usedGas, vm.Config{}) + if err != nil { + t.Fatalf("failed to apply transaction: %v", err) + } + + // Verify receipt status + if receipt.Status != types.ReceiptStatusSuccessful { + t.Errorf("expected transaction to succeed, got status %d", receipt.Status) + } + + msg, err := TransactionToMessage(tx, signer, baseFee, headerGasTip, stateDB) + if err != nil { + t.Fatalf("failed to convert transaction to message: %v", err) + } + + // Verify that normal account uses header's gas tip (not transaction's GasTipCap) + if msg.GasTipCap.Cmp(headerGasTip) != 0 { + t.Errorf("expected GasTipCap %v (headerGasTip), got %v (tx.GasTipCap was %v but should be ignored)", + headerGasTip, msg.GasTipCap, txGasTipCap) + } + + // Calculate expected effective gas price for normal account + // Normal account uses headerGasTip, so effectiveGasPrice = baseFee + headerGasTip + expectedEffectiveGasPrice := new(big.Int).Add(baseFee, headerGasTip) + if txGasFeeCap.Cmp(expectedEffectiveGasPrice) < 0 { + t.Errorf("txGasFeeCap is less than expectedEffectiveGasPrice") + } + + anzeonGasTip := types.NewInstantAnzeonTipEnv(signer, baseFee, headerGasTip, stateDB) + actualEffectiveGasPrice, _ := tx.EffectiveGasTip(anzeonGasTip) + if actualEffectiveGasPrice == nil { + t.Errorf("actualEffectiveGasPrice is nil") + } + actualEffectiveGasPrice = actualEffectiveGasPrice.Add(actualEffectiveGasPrice, baseFee) + + // Verify effective gas price matches expected value + if actualEffectiveGasPrice.Cmp(expectedEffectiveGasPrice) != 0 { + t.Errorf("expected effective gas price %v (baseFee %v + headerGasTip %v, capped by GasFeeCap %v), got %v", + expectedEffectiveGasPrice, baseFee, headerGasTip, txGasFeeCap, actualEffectiveGasPrice) + } + + // Calculate and verify total gas fee paid + expectedTotalGasFee := new(big.Int).Mul(big.NewInt(int64(receipt.GasUsed)), expectedEffectiveGasPrice) + actualTotalGasFee := new(big.Int).Mul(big.NewInt(int64(receipt.GasUsed)), actualEffectiveGasPrice) + + if actualTotalGasFee.Cmp(expectedTotalGasFee) != 0 { + t.Errorf("expected total gas fee %v (GasUsed %d * effectiveGasPrice %v), got %v", + expectedTotalGasFee, receipt.GasUsed, expectedEffectiveGasPrice, actualTotalGasFee) + } + + t.Logf("Normal account - GasUsed: %d, EffectiveGasPrice: %v, TotalGasFee: %v", + receipt.GasUsed, actualEffectiveGasPrice, actualTotalGasFee) +} diff --git a/core/state_transition.go b/core/state_transition.go index d644ee44a..6f9cdeff6 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" cmath "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto/kzg4844" @@ -151,10 +152,19 @@ type Message struct { } // TransactionToMessage converts a transaction into a Message. -func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee, headerGasTip *big.Int) (*Message, error) { +func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee, headerGasTip *big.Int, statedb *state.StateDB) (*Message, error) { + from, err := types.Sender(s, tx) + if err != nil { + return nil, err + } + gasTipCap := new(big.Int).Set(tx.GasTipCap()) if headerGasTip != nil { - gasTipCap = new(big.Int).Set(headerGasTip) + // If Anzeon is enabled, and the sender is authorized, use the tx's tx.GasTipCap() + // Otherwise, use the header's gas tip + if statedb != nil && !statedb.IsAuthorized(from) { + gasTipCap = new(big.Int).Set(headerGasTip) + } } msg := &Message{ @@ -179,8 +189,8 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee, header if tx.FeePayer() != nil { msg.FeePayer = tx.FeePayer() } - var err error - msg.From, err = types.Sender(s, tx) + + msg.From = from return msg, err } diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 7c0a06b14..ebafa5257 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -232,6 +233,9 @@ type LegacyPool struct { initDoneCh chan struct{} // is closed once the pool is initialized (for tests) changesSinceReorg int // A counter for how many drops we've performed in-between reorg. + + // anzeon gas tip environment + anzeonTipEnv *gasprice.AnzeonTipEnv } type txpoolResetRequest struct { @@ -266,7 +270,8 @@ func New(config Config, chain BlockChain) *LegacyPool { log.Info("Setting new local account", "address", addr) pool.locals.add(addr) } - pool.priced = newPricedList(pool.all) + pool.anzeonTipEnv = gasprice.NewAnzeonTipEnv(chain.Config(), chain.StateAt) + pool.priced = newPricedList(pool.all, pool.anzeonTipEnv) if !config.NoLocals && config.Journal != "" { pool.journal = newTxJournal(config.Journal) @@ -309,6 +314,7 @@ func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.A pool.currentHead.Store(head) pool.currentState = statedb pool.pendingNonces = newNoncer(statedb) + pool.anzeonTipEnv.SetCurrentBlock(head) // Start the reorg loop early, so it can handle requests generated during // journal loading. @@ -539,14 +545,14 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address] // Convert the new uint256.Int types to the old big.Int ones used by the legacy pool var ( - minTipBig *big.Int - baseFeeBig *big.Int + minTipBig *big.Int ) if filter.MinTip != nil { minTipBig = filter.MinTip.ToBig() } + pool.anzeonTipEnv.SetCurrentBlock(filter.NewHeader) // filter.NewHeader can be nil, but it doesn't matter if filter.BaseFee != nil { - baseFeeBig = filter.BaseFee.ToBig() + pool.anzeonTipEnv.SetBaseFee(filter.BaseFee.ToBig()) } pending := make(map[common.Address][]*txpool.LazyTransaction, len(pool.pending)) for addr, list := range pool.pending { @@ -555,7 +561,7 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address] // If the miner requests tip enforcement, cap the lists now if minTipBig != nil && !pool.locals.contains(addr) { for i, tx := range txs { - if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 { + if tx.EffectiveGasTipIntCmp(minTipBig, pool.anzeonTipEnv) < 0 { txs = txs[:i] break } @@ -1280,6 +1286,7 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, promoteAddrs = dirtyAccounts.flatten() } pool.mu.Lock() + if reset != nil { // Reset from the old head to the new, rescheduling any reorged transactions pool.reset(reset.oldHead, reset.newHead) @@ -1308,10 +1315,9 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, if reset.newHead != nil { if pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead) - pool.priced.SetBaseFee(pendingBaseFee) - } else { - pool.priced.Reheap() + pool.anzeonTipEnv.SetBaseFee(pendingBaseFee) } + pool.priced.Reheap() } // Update all accounts to the latest known pending nonce nonces := make(map[common.Address]uint64, len(pool.pending)) @@ -1438,6 +1444,7 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { pool.currentHead.Store(newHead) pool.currentState = statedb pool.pendingNonces = newNoncer(statedb) + pool.anzeonTipEnv.SetCurrentBlock(newHead) // update tip env if new head is given // Inject any transactions discarded due to reorgs log.Debug("Reinjecting stale transactions", "count", len(reinject)) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 7ea7ac8fb..d857ffe91 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -2060,19 +2060,22 @@ func TestDualHeapEviction(t *testing.T) { highTip = tx } else { tx = dynamicFeeTx(0, 100000, big.NewInt(int64(baseFee+200+i)), big.NewInt(1), key) - highCap = tx + if highCap == nil || highCap.GasFeeCapCmp(tx) < 0 { + highCap = tx + } } pool.addRemotesSync([]*types.Transaction{tx}) } pending, queued := pool.Stats() if pending+queued != 20 { - t.Fatalf("transaction count mismatch: have %d, want %d", pending+queued, 10) + t.Fatalf("transaction count mismatch: have %d, want %d", pending+queued, 20) } } add(false) for baseFee = 0; baseFee <= 1000; baseFee += 100 { - pool.priced.SetBaseFee(big.NewInt(int64(baseFee))) + pool.anzeonTipEnv.SetBaseFee(big.NewInt(int64(baseFee))) + pool.priced.Reheap() add(true) check(highCap, "fee cap") add(false) diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go index 489f94fe4..59f5dc65e 100644 --- a/core/txpool/legacypool/list.go +++ b/core/txpool/legacypool/list.go @@ -25,9 +25,8 @@ import ( "sync/atomic" "time" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" "golang.org/x/exp/slices" @@ -476,12 +475,10 @@ func (l *list) subTotalCost(txs []*types.Transaction) { } // priceHeap is a heap.Interface implementation over transactions for retrieving -// price-sorted transactions to discard when the pool fills up. If baseFee is set -// then the heap is sorted based on the effective tip based on the given base fee. -// If baseFee is nil then the sorting is based on gasFeeCap. +// price-sorted transactions to discard when the pool fills up. type priceHeap struct { - baseFee *big.Int // heap should always be re-sorted after baseFee is changed - list []*types.Transaction + list []*types.Transaction + anzeonTipEnv types.AnzeonGasTipEnv } func (h *priceHeap) Len() int { return len(h.list) } @@ -499,17 +496,22 @@ func (h *priceHeap) Less(i, j int) bool { } func (h *priceHeap) cmp(a, b *types.Transaction) int { - if h.baseFee != nil { + anzeonTipSame := false + if h.anzeonTipEnv != nil && h.anzeonTipEnv.GetBaseFee() != nil { // Compare effective tips if baseFee is specified - if c := a.EffectiveGasTipCmp(b, h.baseFee); c != 0 { + if c := a.EffectiveGasTipCmp(b, h.anzeonTipEnv); c != 0 { return c } + anzeonTipSame = true } // Compare fee caps if baseFee is not specified or effective tips are equal if c := a.GasFeeCapCmp(b); c != 0 { return c } // Compare tips if effective tips and fee caps are equal + if anzeonTipSame { + return 0 + } return a.GasTipCapCmp(b) } @@ -554,10 +556,13 @@ const ( ) // newPricedList creates a new price-sorted transaction heap. -func newPricedList(all *lookup) *pricedList { - return &pricedList{ +func newPricedList(all *lookup, anzeonTipEnv types.AnzeonGasTipEnv) *pricedList { + result := &pricedList{ all: all, } + result.urgent.anzeonTipEnv = anzeonTipEnv + result.floating.anzeonTipEnv = anzeonTipEnv + return result } // Put inserts a new transaction into the heap. @@ -664,6 +669,7 @@ func (l *pricedList) Reheap() { start := time.Now() l.stales.Store(0) l.urgent.list = make([]*types.Transaction, 0, l.all.RemoteCount()) + l.all.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool { l.urgent.list = append(l.urgent.list, tx) return true @@ -683,10 +689,3 @@ func (l *pricedList) Reheap() { heap.Init(&l.floating) reheapTimer.Update(time.Since(start)) } - -// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not -// necessary to call right before SetBaseFee when processing a new block. -func (l *pricedList) SetBaseFee(baseFee *big.Int) { - l.urgent.baseFee = baseFee - l.Reheap() -} diff --git a/core/txpool/legacypool/list_test.go b/core/txpool/legacypool/list_test.go index 44a42cff3..45ff98b18 100644 --- a/core/txpool/legacypool/list_test.go +++ b/core/txpool/legacypool/list_test.go @@ -17,6 +17,7 @@ package legacypool import ( + "container/heap" "math/big" "math/rand" "testing" @@ -110,3 +111,788 @@ func BenchmarkListCapOneTx(b *testing.B) { b.StopTimer() } } + +type testAnzeonTipEnv struct { + baseFee *big.Int + headerTip *big.Int + isAuthorized map[common.Hash]bool +} + +func newTestAnzeonTipEnv() *testAnzeonTipEnv { + return &testAnzeonTipEnv{ + isAuthorized: make(map[common.Hash]bool), + } +} + +func (atEnv *testAnzeonTipEnv) GetBaseFee() *big.Int { + return atEnv.baseFee +} + +func (atEnv *testAnzeonTipEnv) GetAnzeonTipCap(tx *types.Transaction) *big.Int { + if ok, is := atEnv.isAuthorized[tx.Hash()]; !ok || !is { + if atEnv.headerTip == nil { + return tx.GasTipCap() + } + return atEnv.headerTip + } + return tx.GasTipCap() +} + +func (atEnv *testAnzeonTipEnv) SetCurrentBlock(header *types.Header) { + // not used +} + +func (atEnv *testAnzeonTipEnv) SetBaseFee(baseFee *big.Int) { + atEnv.baseFee = baseFee +} + +func (atEnv *testAnzeonTipEnv) SetHeaderGasTip(headerGasTip *big.Int) { + atEnv.headerTip = headerGasTip +} + +func (atEnv *testAnzeonTipEnv) SetAuthorized(tx *types.Transaction, authorized bool) { + atEnv.isAuthorized[tx.Hash()] = authorized +} + +// TestPricedListIntegration tests the complete pricedList functionality including +// Put, PutAnzeon, Pop, Underpriced, SetBaseFee, SetHeaderGasTip, and all cmp/Less conditions +func TestPricedListIntegration(t *testing.T) { + lookup := newLookup() + anzeonTipEnv := newTestAnzeonTipEnv() + priced := newPricedList(lookup, anzeonTipEnv) + + // Generate keys for different accounts + authorizedKey1, _ := crypto.GenerateKey() + authorizedKey2, _ := crypto.GenerateKey() + normalKey1, _ := crypto.GenerateKey() + normalKey2, _ := crypto.GenerateKey() + normalKey3, _ := crypto.GenerateKey() + + // ============================================ + // Test Case 1: Anzeon Disabled, baseFee = nil, headerGasTip = nil + // ============================================ + t.Logf("=== Test Case 1: Anzeon Disabled, baseFee = nil, headerGasTip = nil ===") + + // Create transactions with different feeCaps (no baseFee, no headerGasTip, so compare by feeCap) + tx1 := dynamicFeeTx(0, 21000, big.NewInt(50000), big.NewInt(20000), authorizedKey1) // feeCap=50000 + tx2 := dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(15000), authorizedKey2) // feeCap=40000 + tx3 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(10000), normalKey1) // feeCap=30000 + + lookup.Add(tx1, false) + lookup.Add(tx2, false) + lookup.Add(tx3, false) + + priced.Put(tx1, false) + priced.Put(tx2, false) + priced.Put(tx3, false) + + // Reheap to initialize heap + priced.Reheap() + + // Verify order: tx1 (50000) > tx2 (40000) > tx3 (30000) + popped1_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped1_1.Hash() != tx3.Hash() { + t.Errorf("Expected tx3 (feeCap=30000) to be popped first, got tx with feeCap=%s", popped1_1.GasFeeCap().String()) + } + + popped1_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped1_2.Hash() != tx2.Hash() { + t.Errorf("Expected tx2 (feeCap=40000) to be popped second, got tx with feeCap=%s", popped1_2.GasFeeCap().String()) + } + + popped1_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped1_3.Hash() != tx1.Hash() { + t.Errorf("Expected tx1 (feeCap=50000) to be popped last, got tx with feeCap=%s", popped1_3.GasFeeCap().String()) + } + + // ============================================ + // Test Case 2: Anzeon Disabled, baseFee exists, headerGasTip = nil + // ============================================ + t.Logf("=== Test Case 2: Anzeon Disabled, baseFee = 10000, headerGasTip = nil ===") + + // Clear and reset + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + // Set baseFee + baseFee := big.NewInt(10000) + anzeonTipEnv.SetBaseFee(baseFee) + + // effectiveTip = min(tipCap, feeCap - baseFee) + + // Create transactions with same feeCap but different effectiveTips + // tx4: feeCap=30000, tipCap=20000 -> effectiveTip=min(20000, 20000)=20000 + tx4 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + // tx5: feeCap=30000, tipCap=15000 -> effectiveTip=min(15000, 20000)=15000 + tx5 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(15000), authorizedKey2) + // tx6: feeCap=30000, tipCap=10000 -> effectiveTip=min(10000, 20000)=10000 + tx6 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(10000), normalKey1) + + lookup.Add(tx4, false) + lookup.Add(tx5, false) + lookup.Add(tx6, false) + + priced.Put(tx4, false) + priced.Put(tx5, false) + priced.Put(tx6, false) + + priced.Reheap() + + // Verify order: tx4 (effectiveTip=20000) > tx5 (15000) > tx6 (10000) + popped2_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped2_1.Hash() != tx6.Hash() { + t.Errorf("Expected tx6 (effectiveTip=10000) to be popped first") + } + + popped2_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped2_2.Hash() != tx5.Hash() { + t.Errorf("Expected tx5 (effectiveTip=15000) to be popped second") + } + + popped2_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped2_3.Hash() != tx4.Hash() { + t.Errorf("Expected tx4 (effectiveTip=20000) to be popped last") + } + + // ============================================ + // Test Case 3: Anzeon Enabled, baseFee exists, headerGasTip exists + // ============================================ + t.Logf("=== Test Case 3: Anzeon Enabled, baseFee = 10000, headerGasTip = 10000 ===") + + // Clear and reset + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + baseFee = big.NewInt(10000) + headerGasTip := big.NewInt(10000) + anzeonTipEnv.SetBaseFee(baseFee) + anzeonTipEnv.SetHeaderGasTip(headerGasTip) + + //effectiveTip = min(tipCap, feeCap - baseFee) + + // Authorized transactions use their own GasTipCap + // authTx1: feeCap=30000, tipCap=20000 -> effectiveTip=min(20000, 20000)=20000 + authTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + // authTx2: feeCap=30000, tipCap=15000 -> effectiveTip=min(15000, 20000)=15000 + authTx2 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(15000), authorizedKey2) + + // Normal transactions use headerGasTip (10000) + // normTx1: feeCap=30000, tipCap=25000 (ignored) -> effectiveTip=min(10000, 20000)=10000 + normTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(25000), normalKey1) + // normTx2: feeCap=25000, tipCap=20000 (ignored) -> effectiveTip=min(10000, 15000)=10000 + normTx2 := dynamicFeeTx(0, 21000, big.NewInt(25000), big.NewInt(20000), normalKey2) + + lookup.Add(authTx1, false) + lookup.Add(authTx2, false) + lookup.Add(normTx1, false) + lookup.Add(normTx2, false) + + anzeonTipEnv.SetAuthorized(authTx1, true) + anzeonTipEnv.SetAuthorized(authTx2, true) + anzeonTipEnv.SetAuthorized(normTx1, false) + anzeonTipEnv.SetAuthorized(normTx2, false) + priced.Put(authTx1, false) + priced.Put(authTx2, false) + priced.Put(normTx1, false) + priced.Put(normTx2, false) + + priced.Reheap() + + // Verify order: authTx1 (20000) > authTx2 (15000) > normTx1 (10000, feeCap=30000) > normTx2 (10000, feeCap=25000) + popped3_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped3_1.Hash() != normTx2.Hash() { + t.Errorf("Expected normTx2 (effectiveTip=10000, feeCap=25000) to be popped first") + } + + popped3_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped3_2.Hash() != normTx1.Hash() { + t.Errorf("Expected normTx1 (effectiveTip=10000, feeCap=30000) to be popped second") + } + + popped3_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped3_3.Hash() != authTx2.Hash() { + t.Errorf("Expected authTx2 (effectiveTip=15000) to be popped third") + } + + popped3_4 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped3_4.Hash() != authTx1.Hash() { + t.Errorf("Expected authTx1 (effectiveTip=20000) to be popped last") + } + + // ============================================ + // Test Case 4: Same effectiveTip, compare by feeCap + // ============================================ + t.Logf("=== Test Case 4: Same effectiveTip, compare by feeCap ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + anzeonTipEnv.SetHeaderGasTip(big.NewInt(10000)) + + // effectiveTip = min(tipCap, feeCap - baseFee) + + // Normal transactions use headerGasTip (10000) + // All have effectiveTip=10000, but different feeCaps + // normTx3: feeCap=40000, tipCap=30000(ignored) -> effectiveTip=min(10000, 40000-10000)=10000 + normTx3 := dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(30000), normalKey3) + // normTx4: feeCap=35000, tipCap=30000(ignored) -> effectiveTip=min(10000, 35000-10000)=10000 + normTx4 := dynamicFeeTx(0, 21000, big.NewInt(35000), big.NewInt(30000), normalKey1) + // normTx5: feeCap=30000, tipCap=30000(ignored) -> effectiveTip=min(10000, 30000-10000)=10000 + normTx5 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(30000), normalKey2) + + lookup.Add(normTx3, false) + lookup.Add(normTx4, false) + lookup.Add(normTx5, false) + + priced.Put(normTx3, false) + priced.Put(normTx4, false) + priced.Put(normTx5, false) + + priced.Reheap() + + // Verify order: normTx5 (30000) < normTx4 (35000) < normTx3 (40000) + popped4_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped4_1.Hash() != normTx5.Hash() { + t.Errorf("Expected normTx5 (feeCap=30000) to be popped first") + } + + popped4_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped4_2.Hash() != normTx4.Hash() { + t.Errorf("Expected normTx4 (feeCap=35000) to be popped second") + } + + popped4_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped4_3.Hash() != normTx3.Hash() { + t.Errorf("Expected normTx3 (feeCap=40000) to be popped last") + } + + // ============================================ + // Test Case 5: Same effectiveTip and feeCap, compare by tipCap + // ============================================ + t.Logf("=== Test Case 5: Same effectiveTip and feeCap, compare by tipCap ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + anzeonTipEnv.SetHeaderGasTip(big.NewInt(10000)) + + // effectiveTip = min(tipCap, feeCap - baseFee) + // All have same feeCap=30000, but different tipCaps (for authorized accounts) + // authTx3: tipCap=20000 -> effectiveTip=min(20000, 30000-10000)=min(20000, 20000)=20000 + authTx3 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + // authTx4: tipCap=15000 -> effectiveTip=min(15000, 30000-10000)=min(15000, 20000)=15000 + authTx4 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(15000), authorizedKey2) + + lookup.Add(authTx3, false) + lookup.Add(authTx4, false) + + anzeonTipEnv.SetAuthorized(authTx3, true) + anzeonTipEnv.SetAuthorized(authTx4, true) + priced.Put(authTx3, false) + priced.Put(authTx4, false) + + priced.Reheap() + + // Verify order: authTx4 (effectiveTip=15000) < authTx3 (effectiveTip=20000) + popped5_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped5_1.Hash() != authTx4.Hash() { + t.Errorf("Expected authTx4 (effectiveTip=15000) to be popped first") + } + + popped5_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped5_2.Hash() != authTx3.Hash() { + t.Errorf("Expected authTx3 (effectiveTip=20000) to be popped last") + } + + // ============================================ + // Test Case 6a: Same effectiveTip, feeCap, tipCap - compare by nonce (reverse) + // ============================================ + t.Logf("=== Test Case 6: Same effectiveTip, feeCap, tipCap - compare by nonce (reverse) ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + anzeonTipEnv.SetHeaderGasTip(big.NewInt(10000)) + + // All values identical, different nonces + // sameTx1: nonce=0 + sameTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + // sameTx2: nonce=1 + sameTx2 := dynamicFeeTx(1, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + // sameTx3: nonce=2 + sameTx3 := dynamicFeeTx(2, 21000, big.NewInt(30000), big.NewInt(20000), authorizedKey1) + + lookup.Add(sameTx1, false) + lookup.Add(sameTx2, false) + lookup.Add(sameTx3, false) + + anzeonTipEnv.SetAuthorized(sameTx1, true) + anzeonTipEnv.SetAuthorized(sameTx2, true) + anzeonTipEnv.SetAuthorized(sameTx3, true) + + priced.Put(sameTx1, false) + priced.Put(sameTx2, false) + priced.Put(sameTx3, false) + + priced.Reheap() + + // Verify order: nonce reverse (higher nonce first) + // sameTx3 (nonce=2) < sameTx2 (nonce=1) < sameTx1 (nonce=0) + popped6a_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6a_1.Hash() != sameTx3.Hash() { + t.Errorf("Expected sameTx3 (nonce=2) to be popped first") + } + + popped6a_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6a_2.Hash() != sameTx2.Hash() { + t.Errorf("Expected sameTx2 (nonce=1) to be popped second") + } + + popped6a_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6a_3.Hash() != sameTx1.Hash() { + t.Errorf("Expected sameTx1 (nonce=0) to be popped last") + } + + // ============================================ + // Test Case 6b: nonce comparison (Anzeon disabled, no baseFee) + // ============================================ + t.Logf("=== Test Case 6b: nonce comparison (Anzeon disabled, no baseFee) ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + // No baseFee, no headerGasTip (Anzeon disabled) + // All transactions have same feeCap and tipCap + // nonceTx1: nonce=0, feeCap=30000, tipCap=20000 + nonceTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + // nonceTx2: nonce=1, feeCap=30000, tipCap=20000 + nonceTx2 := dynamicFeeTx(1, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + // nonceTx3: nonce=2, feeCap=30000, tipCap=20000 + nonceTx3 := dynamicFeeTx(2, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + + lookup.Add(nonceTx1, false) + lookup.Add(nonceTx2, false) + lookup.Add(nonceTx3, false) + + priced.Put(nonceTx1, false) + priced.Put(nonceTx2, false) + priced.Put(nonceTx3, false) + + priced.Reheap() + + // Verify order: nonce reverse (higher nonce first) + // nonceTx3 (nonce=2) < nonceTx2 (nonce=1) < nonceTx1 (nonce=0) + popped6b_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6b_1.Hash() != nonceTx3.Hash() { + t.Errorf("Expected nonceTx3 (nonce=2) to be popped first") + } + + popped6b_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6b_2.Hash() != nonceTx2.Hash() { + t.Errorf("Expected nonceTx2 (nonce=1) to be popped second") + } + + popped6b_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6b_3.Hash() != nonceTx1.Hash() { + t.Errorf("Expected nonceTx1 (nonce=0) to be popped last") + } + + // ============================================ + // Test Case 6c: nonce comparison (Anzeon disabled, with baseFee) + // ============================================ + t.Logf("=== Test Case 6c: nonce comparison (Anzeon disabled, with baseFee) ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + // No headerGasTip (Anzeon disabled) + + // All transactions have same feeCap, tipCap, and effectiveTip + // baseNonceTx1: nonce=0, feeCap=30000, tipCap=20000 -> effectiveTip=min(20000, 20000)=20000 + baseNonceTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + // baseNonceTx2: nonce=1, feeCap=30000, tipCap=20000 -> effectiveTip=min(20000, 20000)=20000 + baseNonceTx2 := dynamicFeeTx(1, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + // baseNonceTx3: nonce=2, feeCap=30000, tipCap=20000 -> effectiveTip=min(20000, 20000)=20000 + baseNonceTx3 := dynamicFeeTx(2, 21000, big.NewInt(30000), big.NewInt(20000), normalKey1) + + lookup.Add(baseNonceTx1, false) + lookup.Add(baseNonceTx2, false) + lookup.Add(baseNonceTx3, false) + + priced.Put(baseNonceTx1, false) + priced.Put(baseNonceTx2, false) + priced.Put(baseNonceTx3, false) + + priced.Reheap() + + // Verify order: nonce reverse (higher nonce first) + // baseNonceTx3 (nonce=2) < baseNonceTx2 (nonce=1) < baseNonceTx1 (nonce=0) + popped6c_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6c_1.Hash() != baseNonceTx3.Hash() { + t.Errorf("Expected baseNonceTx3 (nonce=2) to be popped first") + } + + popped6c_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6c_2.Hash() != baseNonceTx2.Hash() { + t.Errorf("Expected baseNonceTx2 (nonce=1) to be popped second") + } + + popped6c_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6c_3.Hash() != baseNonceTx1.Hash() { + t.Errorf("Expected baseNonceTx1 (nonce=0) to be popped last") + } + + // ============================================ + // Test Case 6d: nonce comparison (Anzeon enabled, mixed accounts) + // ============================================ + t.Logf("=== Test Case 6d: All nonce comparison (Anzeon enabled, mixed accounts) ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + anzeonTipEnv.SetHeaderGasTip(big.NewInt(20000)) // Same as tipCap for authorized + + // All transactions have same effectiveTip, feeCap + // mixedNonceTx1: nonce=0, authorized, feeCap=40000, tipCap=20000 -> effectiveTip=min(20000, 40000-10000)=20000 + mixedNonceTx1 := dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(20000), authorizedKey1) + // mixedNonceTx2: nonce=1, normal, feeCap=40000, tipCap=30000(ignored) -> effectiveTip=min(20000, 40000-10000)=20000 + mixedNonceTx2 := dynamicFeeTx(1, 21000, big.NewInt(40000), big.NewInt(30000), normalKey1) + // mixedNonceTx3: nonce=2, authorized, feeCap=40000, tipCap=20000 -> effectiveTip=min(20000, 40000-10000)=20000 + mixedNonceTx3 := dynamicFeeTx(2, 21000, big.NewInt(40000), big.NewInt(20000), authorizedKey2) + + lookup.Add(mixedNonceTx1, false) + lookup.Add(mixedNonceTx2, false) + lookup.Add(mixedNonceTx3, false) + + anzeonTipEnv.SetAuthorized(mixedNonceTx1, true) + anzeonTipEnv.SetAuthorized(mixedNonceTx2, false) + anzeonTipEnv.SetAuthorized(mixedNonceTx3, true) + + priced.Put(mixedNonceTx1, false) + priced.Put(mixedNonceTx2, false) + priced.Put(mixedNonceTx3, false) + + priced.Reheap() + + // All have same effectiveTip (20000), feeCap (40000), tipCap (20000), normal account uses headerGasTip=20000) + // Should compare by nonce reverse: nonce=2 < nonce=1 < nonce=0 + popped6d_1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6d_1.Hash() != mixedNonceTx3.Hash() { + t.Errorf("Expected mixedNonceTx3 (nonce=2) to be popped first") + } + + popped6d_2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6d_2.Hash() != mixedNonceTx2.Hash() { + t.Errorf("Expected mixedNonceTx2 (nonce=1) to be popped second") + } + + popped6d_3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped6d_3.Hash() != mixedNonceTx1.Hash() { + t.Errorf("Expected mixedNonceTx1 (nonce=0) to be popped last") + } + + // ============================================ + // Test Case 7: Underpriced check + // ============================================ + t.Logf("=== Test Case 7: Underpriced check ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + anzeonTipEnv.SetBaseFee(big.NewInt(10000)) + anzeonTipEnv.SetHeaderGasTip(big.NewInt(10000)) + + // Add multiple transactions to ensure both urgent and floating heaps have items + // highTx: effectiveTip=min(30000, 40000)=30000 + highTx := dynamicFeeTx(0, 21000, big.NewInt(50000), big.NewInt(30000), authorizedKey1) + // midTx: effectiveTip=min(20000, 40000)=20000 + midTx := dynamicFeeTx(0, 21000, big.NewInt(45000), big.NewInt(20000), authorizedKey2) + // lowTx: effectiveTip=min(10000, 30000)=10000 + veryLowTx := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(10000), normalKey1) + + lookup.Add(highTx, false) + lookup.Add(midTx, false) + lookup.Add(veryLowTx, false) + + anzeonTipEnv.SetAuthorized(highTx, true) + anzeonTipEnv.SetAuthorized(midTx, true) + anzeonTipEnv.SetAuthorized(veryLowTx, false) + + priced.Put(highTx, false) + priced.Put(midTx, false) + priced.Put(veryLowTx, false) + + priced.Reheap() + + // After Reheap, some transactions may be in floating heap + // The minimum priority transaction (worst) should be in one of the heaps + + // Create a lower-priority transaction than the worst one + // lowTx: effectiveTip=min(5000, 10000)=5000 + lowTx := dynamicFeeTx(0, 21000, big.NewInt(20000), big.NewInt(5000), normalKey2) + + // lowTx should be underpriced (worse than the worst transaction in heaps) + if !priced.Underpriced(lowTx) { + t.Errorf("Expected lowTx to be underpriced") + } + + // Create a much higher-priority transaction + // higherTx: effectiveTip=min(40000, 50000)=40000, feeCap=60000 + higherTx := dynamicFeeTx(0, 21000, big.NewInt(60000), big.NewInt(40000), authorizedKey1) + + // higherTx should NOT be underpriced (better than all transactions in heaps) + if priced.Underpriced(higherTx) { + t.Errorf("Expected higherTx NOT to be underpriced (effectiveTip=40000 > all others)") + } + + // ============================================ + // Test Case 8: Change headerGasTip + // ============================================ + t.Logf("=== Test Case 8: Change headerGasTip ===") + + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + // Initial settings: baseFee=10000, headerGasTip=10000 + baseFee = big.NewInt(10000) + headerGasTip = big.NewInt(10000) + anzeonTipEnv.SetBaseFee(baseFee) + anzeonTipEnv.SetHeaderGasTip(headerGasTip) + + // Add multiple transactions to see sorting effects + // Conditions: + // - GasTipCap >= headerGasTip (all accounts) + // - GasFeeCap >= headerGasTip + baseFee (normal accounts) + // - GasFeeCap >= GasTipCap + baseFee (authorized accounts) + + // Authorized transactions + // dynAuthTx1: effectiveTip=min(20000, 40000-10000)=min(20000, 30000)=20000 + dynAuthTx1 := dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(20000), authorizedKey1) + // dynAuthTx2: effectiveTip=min(15000, 30000-10000)=min(15000, 20000)=15000 + dynAuthTx2 := dynamicFeeTx(1, 21000, big.NewInt(30000), big.NewInt(15000), authorizedKey2) + + // Normal transactions (use headerGasTip=10000) + // dynNormTx1: effectiveTip=min(10000, 30000-10000)=min(10000, 20000)=10000 + dynNormTx1 := dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(25000), normalKey1) + // dynNormTx2: effectiveTip=min(10000, 35000-10000)=min(10000, 25000)=10000 + dynNormTx2 := dynamicFeeTx(0, 21000, big.NewInt(35000), big.NewInt(30000), normalKey2) + // dynNormTx3: effectiveTip=min(10000, 25000-10000)=min(10000, 15000)=10000 + dynNormTx3 := dynamicFeeTx(0, 21000, big.NewInt(25000), big.NewInt(20000), normalKey3) + + lookup.Add(dynAuthTx1, false) + lookup.Add(dynAuthTx2, false) + lookup.Add(dynNormTx1, false) + lookup.Add(dynNormTx2, false) + lookup.Add(dynNormTx3, false) + + anzeonTipEnv.SetAuthorized(dynAuthTx1, true) + anzeonTipEnv.SetAuthorized(dynAuthTx2, true) + anzeonTipEnv.SetAuthorized(dynNormTx1, false) + anzeonTipEnv.SetAuthorized(dynNormTx2, false) + anzeonTipEnv.SetAuthorized(dynNormTx3, false) + + priced.Put(dynAuthTx1, false) + priced.Put(dynAuthTx2, false) + priced.Put(dynNormTx1, false) + priced.Put(dynNormTx2, false) + priced.Put(dynNormTx3, false) + + priced.Reheap() + + // Note: Reheap() moves some transactions to floating heap + // With 5 transactions: floatingCount = 5 * 1 / (4 + 1) = 1 + // So urgent has 4, floating has 1 + + // Initial order (headerGasTip=10000, min-heap: smallest first): + // All normal transactions have effectiveTip=10000, compare by feeCap + // 1. dynNormTx3 (effectiveTip=10000, feeCap=35000) - smallest (lowest priority, moved to floating) + // 2. dynNormTx1 (effectiveTip=10000, feeCap=40000) + // 3. dynNormTx2 (effectiveTip=10000, feeCap=45000) + // 4. dynAuthTx2 (effectiveTip=15000) + // 5. dynAuthTx1 (effectiveTip=20000) - largest (highest priority) + + // Verify initial order in urgent heap (4 transactions remain) + // Note: Reheap() balances heaps, so some transactions move to floating + urgentCount := priced.urgent.Len() + floatingCount := priced.floating.Len() + if urgentCount != 4 { + t.Errorf("Initial: expected 4 transactions in urgent, got %d (floating has %d)", urgentCount, floatingCount) + } + + // Verify floating heap has the smallest transaction (moved by Reheap) + if priced.floating.Len() != 1 { + t.Errorf("Initial: expected 1 transaction in floating, got %d", priced.floating.Len()) + } + + // Pop from urgent and verify sorting order + // After Reheap(), urgent has 4 transactions, floating has 1 + // The smallest transaction (dynNormTx3) is moved to floating + // Expected order in urgent heap (after smallest moved to floating): + // 1. dynNormTx1 (effectiveTip=10000, feeCap=40000) - smallest remaining + // 2. dynNormTx2 (effectiveTip=10000, feeCap=45000) + // 3. dynAuthTx2 (effectiveTip=15000) + // 4. dynAuthTx1 (effectiveTip=20000) + popped1 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped1.Hash() != dynNormTx1.Hash() { + t.Errorf("Initial: expected dynNormTx1 (effectiveTip=10000, feeCap=40000) to be popped first, got feeCap=%s", popped1.GasFeeCap().String()) + } + + popped2 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped2.Hash() != dynNormTx2.Hash() { + t.Errorf("Initial: expected dynNormTx2 (effectiveTip=10000, feeCap=45000) to be popped second, got feeCap=%s", popped2.GasFeeCap().String()) + } + + popped3 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped3.Hash() != dynAuthTx2.Hash() { + t.Errorf("Initial: expected dynAuthTx2 (effectiveTip=15000) to be popped third") + } + + popped4 := heap.Pop(&priced.urgent).(*types.Transaction) + if popped4.Hash() != dynAuthTx1.Hash() { + t.Errorf("Initial: expected dynAuthTx1 (effectiveTip=20000) to be popped fourth") + } + + floatingTx := heap.Pop(&priced.floating).(*types.Transaction) + if floatingTx.Hash() != dynNormTx3.Hash() { + t.Errorf("Initial: expected dynNormTx3 (effectiveTip=10000, feeCap=35000) to be in floating heap") + } + + t.Logf("Initial sorting verified: urgent has 4, floating has 1, all in correct order") + + // Re-add transactions for headerGasTip change test + // Need to create new transactions that satisfy conditions for headerGasTip=25000 + lookup = newLookup() + anzeonTipEnv = newTestAnzeonTipEnv() + priced = newPricedList(lookup, anzeonTipEnv) + + baseFee = big.NewInt(10000) + headerGasTip = big.NewInt(10000) + anzeonTipEnv.SetBaseFee(baseFee) + anzeonTipEnv.SetHeaderGasTip(headerGasTip) + + // Create transactions that satisfy conditions for both headerGasTip=10000 and 25000 + // Authorized transactions (unchanged) + // dynAuthTx1: tipCap=20000 >= headerGasTip(10000, 25000) ✓, feeCap=40000 >= tipCap(20000) + baseFee(10000) = 30000 ✓ + dynAuthTx1 = dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(20000), authorizedKey1) + // dynAuthTx2: tipCap=15000 >= headerGasTip(10000) ✓, feeCap=30000 >= tipCap(15000) + baseFee(10000) = 25000 ✓ + dynAuthTx2 = dynamicFeeTx(0, 21000, big.NewInt(30000), big.NewInt(15000), authorizedKey2) + + // dynNormTx1: headerGasTip=25000: effectiveTip=min(25000, 40000-10000)=min(25000, 30000)=25000 + dynNormTx1 = dynamicFeeTx(0, 21000, big.NewInt(40000), big.NewInt(25000), normalKey1) + // dynNormTx2: headerGasTip=25000: effectiveTip=min(25000, 45000-10000)=min(25000, 35000)=25000 + dynNormTx2 = dynamicFeeTx(0, 21000, big.NewInt(45000), big.NewInt(30000), normalKey2) + // dynNormTx3: headerGasTip=25000: effectiveTip=min(25000, 35000-10000)=min(25000, 25000)=25000 + dynNormTx3 = dynamicFeeTx(0, 21000, big.NewInt(35000), big.NewInt(20000), normalKey3) + + lookup.Add(dynAuthTx1, false) + lookup.Add(dynAuthTx2, false) + lookup.Add(dynNormTx1, false) + lookup.Add(dynNormTx2, false) + lookup.Add(dynNormTx3, false) + + anzeonTipEnv.SetAuthorized(dynAuthTx1, true) + anzeonTipEnv.SetAuthorized(dynAuthTx2, true) + anzeonTipEnv.SetAuthorized(dynNormTx1, false) + anzeonTipEnv.SetAuthorized(dynNormTx2, false) + anzeonTipEnv.SetAuthorized(dynNormTx3, false) + + priced.Put(dynAuthTx1, false) + priced.Put(dynAuthTx2, false) + priced.Put(dynNormTx1, false) + priced.Put(dynNormTx2, false) + priced.Put(dynNormTx3, false) + + priced.Reheap() + + // Initial order (headerGasTip=10000, min-heap: smallest first): + // All normal transactions have effectiveTip=10000, compare by feeCap + // 1. dynNormTx3 (effectiveTip=10000, feeCap=35000) - smallest (lowest priority) + // 2. dynNormTx1 (effectiveTip=10000, feeCap=40000) + // 3. dynNormTx2 (effectiveTip=10000, feeCap=45000) + // 4. dynAuthTx2 (effectiveTip=15000) + // 5. dynAuthTx1 (effectiveTip=20000) - largest (highest priority) + + // Change headerGasTip from 10000 to 15000 + anzeonTipEnv.SetHeaderGasTip(big.NewInt(15000)) + priced.Reheap() + + // After headerGasTip change to 15000: + // Normal transactions now use headerGasTip=15000 instead of 10000 + // dynAuthTx1: effectiveTip=min(20000, 40000-10000)=min(20000, 30000)=20000 (unchanged) + // dynAuthTx2: effectiveTip=min(15000, 30000-10000)=min(15000, 20000)=15000 (unchanged) + // dynNormTx1: effectiveTip=min(15000, 40000-10000)=min(15000, 30000)=15000 (changed from 10000!) + // dynNormTx2: effectiveTip=min(15000, 45000-10000)=min(15000, 35000)=15000 (changed from 10000!) + // dynNormTx3: effectiveTip=min(15000, 35000-10000)=min(15000, 25000)=15000 (changed from 10000!) + + // New order should be (urgent has 4, floating has 1): + // 1. dynAuthTx2 (effectiveTip=15000, feeCap=30000, nonce=1) - smallest (moved to floating) + // 2. dynNormTx3 (effectiveTip=15000, feeCap=35000, nonce=0) + // 3. dynNormTx1 (effectiveTip=15000, feeCap=40000, nonce=0) + // 4. dynNormTx2 (effectiveTip=15000, feeCap=45000, nonce=0) + // 5. dynAuthTx1 (effectiveTip=20000, feeCap=40000, nonce=0) - largest (highest priority) + + // Verify urgent heap has 4 transactions after headerGasTip change + urgentCountAfter := priced.urgent.Len() + floatingCountAfter := priced.floating.Len() + if urgentCountAfter != 4 { + t.Errorf("After headerGasTip change: expected 4 transactions in urgent, got %d (floating has %d)", urgentCountAfter, floatingCountAfter) + } + + // Verify floating heap has 1 transaction + if priced.floating.Len() != 1 { + t.Errorf("After headerGasTip change: expected 1 transaction in floating, got %d", priced.floating.Len()) + } + + // Pop from urgent and verify sorting order (min-heap: smallest first) + // Note: Reheap() moves the smallest transaction to floating heap using heap.Pop() + // After headerGasTip=25000, the smallest transaction (dynAuthTx2) is moved to floating + // Expected order in urgent heap (after smallest moved to floating): + // 1. dynNormTx3 (effectiveTip=15000, feeCap=35000, nonce=0) + // 2. dynNormTx1 (effectiveTip=15000, feeCap=40000, nonce=0) + // 3. dynNormTx2 (effectiveTip=15000, feeCap=45000, nonce=0) + // 4. dynAuthTx1 (effectiveTip=20000, feeCap=40000, nonce=0) - largest (highest priority) + popped1 = heap.Pop(&priced.urgent).(*types.Transaction) + if popped1.Hash() != dynNormTx3.Hash() { + t.Errorf("After headerGasTip change: expected dynNormTx3 (effectiveTip=15000, feeCap=35000) to be popped first, got feeCap=%s", popped1.GasFeeCap().String()) + } + + popped2 = heap.Pop(&priced.urgent).(*types.Transaction) + if popped2.Hash() != dynNormTx1.Hash() { + t.Errorf("After headerGasTip change: expected dynNormTx1 (effectiveTip=15000, feeCap=40000) to be popped second, got feeCap=%s", popped2.GasFeeCap().String()) + } + + popped3 = heap.Pop(&priced.urgent).(*types.Transaction) + if popped3.Hash() != dynNormTx2.Hash() { + t.Errorf("After headerGasTip change: expected dynNormTx2 (effectiveTip=15000, feeCap=45000) to be popped third, got feeCap=%s", popped3.GasFeeCap().String()) + } + + popped4 = heap.Pop(&priced.urgent).(*types.Transaction) + if popped4.Hash() != dynAuthTx1.Hash() { + t.Errorf("After headerGasTip change: expected dynAuthTx1 (effectiveTip=20000, feeCap=40000) to be popped fourth, got feeCap=%s", popped4.GasFeeCap().String()) + } + + floatingTx = heap.Pop(&priced.floating).(*types.Transaction) + if floatingTx.Hash() != dynAuthTx2.Hash() { + t.Errorf("After headerGasTip change: expected dynAuthTx2 (effectiveTip=15000, feeCap=30000) to be in floating heap") + } + + t.Logf("After headerGasTip change: urgent has 4, floating has 1, all in correct order") + t.Logf("HeaderGasTip change from 10000 to 25000 successfully affected normal transactions' effectiveTip") + + t.Logf("=== All test cases passed! ===") +} diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index 9881ed1b8..fff7b72cd 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -77,9 +77,10 @@ type AddressReserver func(addr common.Address, reserve bool) error // a very specific call site in mind and each one can be evaluated very cheaply // by the pool implementations. Only add new ones that satisfy those constraints. type PendingFilter struct { - MinTip *uint256.Int // Minimum miner tip required to include a transaction - BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction - BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction + MinTip *uint256.Int // Minimum miner tip required to include a transaction + BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction + BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction + NewHeader *types.Header // New head header to evaluate tx against (for basefee calculations) OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling) OnlyBlobTxs bool // Return only blob transactions (block blob-space filling) diff --git a/core/types/receipt.go b/core/types/receipt.go index da16a3924..24e58efd0 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -31,6 +31,12 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +// StateReader is an interface for reading state data. +type StateReader interface { + // IsAuthorized returns true if the account is marked as authorized + IsAuthorized(addr common.Address) bool +} + //go:generate go run github.com/fjl/gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go var ( @@ -99,6 +105,7 @@ type storedReceiptRLP struct { PostStateOrStatus []byte CumulativeGasUsed uint64 Logs []*Log + EffectiveGasPrice *big.Int `rlp:"optional"` } // NewReceipt creates a barebone transaction receipt, copying the init fields. @@ -275,6 +282,12 @@ func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error { } } w.ListEnd(logList) + // Write EffectiveGasPrice only if not nil (matches rlp:"optional" semantics) + // When custom EncodeRLP is implemented, we must manually handle optional fields + // by only writing them when they have non-zero values + if r.EffectiveGasPrice != nil { + w.WriteBigInt(r.EffectiveGasPrice) + } w.ListEnd(outerList) return w.Flush() } @@ -291,6 +304,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { } r.CumulativeGasUsed = stored.CumulativeGasUsed r.Logs = stored.Logs + r.EffectiveGasPrice = stored.EffectiveGasPrice r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) return nil @@ -321,9 +335,44 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { } } +type anzeonTipEnv struct { + stateReader StateReader + signer Signer + baseFee *big.Int + headerTip *big.Int +} + +func NewInstantAnzeonTipEnv(signer Signer, baseFee, headerTip *big.Int, stateReader StateReader) AnzeonGasTipEnv { + return &anzeonTipEnv{ + signer: signer, + baseFee: baseFee, + headerTip: headerTip, + stateReader: stateReader, + } +} + +func (atEnv *anzeonTipEnv) GetBaseFee() *big.Int { + return atEnv.baseFee +} + +func (atEnv *anzeonTipEnv) GetAnzeonTipCap(tx *Transaction) *big.Int { + from, err := Sender(atEnv.signer, tx) + if err == nil && atEnv.stateReader != nil && !atEnv.stateReader.IsAuthorized(from) && atEnv.headerTip != nil { + // In Anzeon, normal account gas tip cap is determined by the block header gas tip + return atEnv.headerTip + } + return tx.GasTipCap() +} + +func (atEnv *anzeonTipEnv) SetCurrentBlock(header *Header) { +} + +func (atEnv *anzeonTipEnv) SetBaseFee(baseFee *big.Int) { +} + // DeriveFields fills the receipts with their computed fields based on consensus // data and contextual infos like containing block and transactions. -func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee, headerGasTip *big.Int, blobGasPrice *big.Int, txs []*Transaction) error { +func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee, blobGasPrice *big.Int, txs []*Transaction) error { signer := MakeSigner(config, new(big.Int).SetUint64(number), time) logIndex := uint(0) @@ -334,7 +383,9 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu // The transaction type and hash can be retrieved from the transaction itself rs[i].Type = txs[i].Type() rs[i].TxHash = txs[i].Hash() - rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(baseFee, headerGasTip) + if !config.AnzeonEnabled() { + rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee) + } // EIP-4844 blob transaction fields if txs[i].Type() == BlobTxType { rs[i].BlobGasUsed = txs[i].BlobGas() diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index 9aa43f696..b57053af4 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -125,8 +125,8 @@ var ( Nonce: 5, Value: big.NewInt(5), Gas: 5, - GasTipCap: big.NewInt(1000), - GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(2000), + GasFeeCap: big.NewInt(4000), }), // EIP-4844 transactions. NewTx(&BlobTx{ @@ -144,8 +144,8 @@ var ( Nonce: 7, Value: uint256.NewInt(7), Gas: 7, - GasTipCap: uint256.NewInt(1000), - GasFeeCap: uint256.NewInt(2000), + GasTipCap: uint256.NewInt(1600), + GasFeeCap: uint256.NewInt(3000), BlobFeeCap: uint256.NewInt(100077), BlobHashes: []common.Hash{{}, {}, {}}, }), @@ -258,7 +258,7 @@ var ( // derived fields: TxHash: txs[4].Hash(), GasUsed: 5, - EffectiveGasPrice: big.NewInt(2000), + EffectiveGasPrice: big.NewInt(3000), // anzeon disabled(no sign in tx) BlockHash: blockHash, BlockNumber: blockNumber, TransactionIndex: 4, @@ -286,7 +286,145 @@ var ( // derived fields: TxHash: txs[6].Hash(), GasUsed: 7, + EffectiveGasPrice: big.NewInt(2600), + BlobGasUsed: 3 * params.BlobTxBlobGasPerBlob, + BlobGasPrice: big.NewInt(920), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 6, + }, + } + authorizedReceipts = Receipts{ + &Receipt{ + Status: ReceiptStatusFailed, + CumulativeGasUsed: 1, + Logs: []*Log{ + { + Address: common.BytesToAddress([]byte{0x11}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 0, + }, + { + Address: common.BytesToAddress([]byte{0x01, 0x11}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + Index: 1, + }, + }, + // derived fields: + TxHash: txs[0].Hash(), + ContractAddress: common.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"), + GasUsed: 1, + EffectiveGasPrice: big.NewInt(11), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 0, + }, + &Receipt{ + PostState: common.Hash{2}.Bytes(), + CumulativeGasUsed: 3, + Logs: []*Log{ + { + Address: common.BytesToAddress([]byte{0x22}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 2, + }, + { + Address: common.BytesToAddress([]byte{0x02, 0x22}), + Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, + // derived fields: + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + Index: 3, + }, + }, + // derived fields: + TxHash: txs[1].Hash(), + GasUsed: 2, + EffectiveGasPrice: big.NewInt(22), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 1, + }, + &Receipt{ + Type: AccessListTxType, + PostState: common.Hash{3}.Bytes(), + CumulativeGasUsed: 6, + Logs: []*Log{}, + // derived fields: + TxHash: txs[2].Hash(), + GasUsed: 3, + EffectiveGasPrice: big.NewInt(33), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 2, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{4}.Bytes(), + CumulativeGasUsed: 10, + Logs: []*Log{}, + // derived fields: + TxHash: txs[3].Hash(), + GasUsed: 4, + EffectiveGasPrice: big.NewInt(2000), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 3, + }, + &Receipt{ + Type: DynamicFeeTxType, + PostState: common.Hash{5}.Bytes(), + CumulativeGasUsed: 15, + Logs: []*Log{}, + // derived fields: + TxHash: txs[4].Hash(), + GasUsed: 5, + EffectiveGasPrice: big.NewInt(3000), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 4, + }, + &Receipt{ + Type: BlobTxType, + PostState: common.Hash{6}.Bytes(), + CumulativeGasUsed: 21, + Logs: []*Log{}, + // derived fields: + TxHash: txs[5].Hash(), + GasUsed: 6, EffectiveGasPrice: big.NewInt(2000), + BlobGasUsed: params.BlobTxBlobGasPerBlob, + BlobGasPrice: big.NewInt(920), + BlockHash: blockHash, + BlockNumber: blockNumber, + TransactionIndex: 5, + }, + &Receipt{ + Type: BlobTxType, + PostState: common.Hash{7}.Bytes(), + CumulativeGasUsed: 28, + Logs: []*Log{}, + // derived fields: + TxHash: txs[6].Hash(), + GasUsed: 7, + EffectiveGasPrice: big.NewInt(2600), BlobGasUsed: 3 * params.BlobTxBlobGasPerBlob, BlobGasPrice: big.NewInt(920), BlockHash: blockHash, @@ -310,9 +448,8 @@ func TestDeriveFields(t *testing.T) { // Re-derive receipts. basefee := big.NewInt(1000) blobGasPrice := big.NewInt(920) - headerGasTip := big.NewInt(1000) derivedReceipts := clearComputedFieldsOnReceipts(receipts) - err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, headerGasTip, blobGasPrice, txs) + err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, blobGasPrice, txs) if err != nil { t.Fatalf("DeriveFields(...) = %v, want ", err) } @@ -333,6 +470,33 @@ func TestDeriveFields(t *testing.T) { } } +// Tests that receipt data can be correctly derived for authorized accounts +func TestDeriveFieldsAuthorizedAccount(t *testing.T) { + // Re-derive receipts. + basefee := big.NewInt(1000) + blobGasPrice := big.NewInt(920) + derivedReceipts := clearComputedFieldsOnReceipts(authorizedReceipts) + err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, blobGasPrice, txs) + if err != nil { + t.Fatalf("DeriveFields(...) = %v, want ", err) + } + + // Check diff of receipts against derivedReceipts. + r1, err := json.MarshalIndent(authorizedReceipts, "", " ") + if err != nil { + t.Fatal("error marshaling input receipts:", err) + } + + r2, err := json.MarshalIndent(derivedReceipts, "", " ") + if err != nil { + t.Fatal("error marshaling derived receipts:", err) + } + d := diff.Diff(string(r1), string(r2)) + if d != "" { + t.Fatal("receipts differ:", d) + } +} + // Test that we can marshal/unmarshal receipts to/from json without errors. // This also confirms that our test receipts contain all the required fields. func TestReceiptJSON(t *testing.T) { diff --git a/core/types/transaction.go b/core/types/transaction.go index c881cd055..c61cf98d3 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -52,6 +52,12 @@ const ( FeeDelegateDynamicFeeTxType = 0x16 // fee delegation(22) ) +type AnzeonGasTipEnv interface { + GetBaseFee() *big.Int + GetAnzeonTipCap(tx *Transaction) *big.Int + SetCurrentBlock(header *Header) +} + // Transaction is an Ethereum transaction. type Transaction struct { inner TxData // Consensus contents of a transaction @@ -103,7 +109,8 @@ type TxData interface { // // Unlike other TxData methods, the returned *big.Int should be an independent // copy of the computed value, i.e. callers are allowed to mutate the result. - effectiveGasPrice(baseFee *big.Int, gasTip *big.Int) *big.Int + // Method implementations can use 'dst' to store the result. + effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int encode(*bytes.Buffer) error decode([]byte) error @@ -302,7 +309,9 @@ func (tx *Transaction) Gas() uint64 { return tx.inner.gas() } func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) } // GasTipCap returns the gasTipCap per gas of the transaction. -func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.gasTipCap()) } +func (tx *Transaction) GasTipCap() *big.Int { + return new(big.Int).Set(tx.inner.gasTipCap()) +} // GasFeeCap returns the fee cap per gas of the transaction. func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) } @@ -366,46 +375,39 @@ func (tx *Transaction) GasTipCapIntCmp(other *big.Int) int { // EffectiveGasTip returns the effective miner gasTipCap for the given base fee. // Note: if the effective gasTipCap is negative, this method returns both error // the actual negative value, _and_ ErrGasFeeCapTooLow -func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) { - if baseFee == nil { +func (tx *Transaction) EffectiveGasTip(anzeonTipEnv AnzeonGasTipEnv) (*big.Int, error) { + if anzeonTipEnv == nil || anzeonTipEnv.GetBaseFee() == nil { return tx.GasTipCap(), nil } var err error gasFeeCap := tx.GasFeeCap() - if gasFeeCap.Cmp(baseFee) == -1 { + if gasFeeCap.Cmp(anzeonTipEnv.GetBaseFee()) == -1 { err = ErrGasFeeCapTooLow } - return math.BigMin(tx.GasTipCap(), gasFeeCap.Sub(gasFeeCap, baseFee)), err + return math.BigMin(anzeonTipEnv.GetAnzeonTipCap(tx), gasFeeCap.Sub(gasFeeCap, anzeonTipEnv.GetBaseFee())), err } // EffectiveGasTipValue is identical to EffectiveGasTip, but does not return an // error in case the effective gasTipCap is negative -func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int { - effectiveTip, _ := tx.EffectiveGasTip(baseFee) +func (tx *Transaction) EffectiveGasTipValue(anzeonTipEnv AnzeonGasTipEnv) *big.Int { + effectiveTip, _ := tx.EffectiveGasTip(anzeonTipEnv) return effectiveTip } // EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee. -func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *big.Int) int { - if baseFee == nil { +func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, anzeonTipEnv AnzeonGasTipEnv) int { + if anzeonTipEnv == nil || anzeonTipEnv.GetBaseFee() == nil { return tx.GasTipCapCmp(other) } - return tx.EffectiveGasTipValue(baseFee).Cmp(other.EffectiveGasTipValue(baseFee)) + return tx.EffectiveGasTipValue(anzeonTipEnv).Cmp(other.EffectiveGasTipValue(anzeonTipEnv)) } // EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap. -func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) int { - if baseFee == nil { +func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, anzeonTipEnv AnzeonGasTipEnv) int { + if anzeonTipEnv == nil || anzeonTipEnv.GetBaseFee() == nil { return tx.GasTipCapIntCmp(other) } - return tx.EffectiveGasTipValue(baseFee).Cmp(other) -} - -// EffectiveGasPrice returns the actual gas price the transaction will pay, given the base fee and gasTip. -// This is different from EffectiveGasTip which returns only the miner tip portion. -// The formula is: min(gasTipCap, gasFeeCap - baseFee) + baseFee, capped by gasTip if applicable. -func (tx *Transaction) EffectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { - return tx.inner.effectiveGasPrice(baseFee, headerGasTip) + return tx.EffectiveGasTipValue(anzeonTipEnv).Cmp(other) } // fee delegation diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index c6d80804b..2e21b8cd0 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -108,8 +108,8 @@ func (tx *AccessListTx) value() *big.Int { return tx.Value } func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } func (tx *AccessListTx) to() *common.Address { return tx.To } -func (tx *AccessListTx) effectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { - return new(big.Int).Set(tx.GasPrice) +func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + return dst.Set(tx.GasPrice) } func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) { diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index 6e669674f..ab79cde10 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -163,19 +163,13 @@ func (tx *BlobTx) nonce() uint64 { return tx.Nonce } func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp } func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) } -func (tx *BlobTx) effectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { +func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { if baseFee == nil { - baseFee = common.Big0 + baseFee = big.NewInt(0) } - - tipCap := tx.GasTipCap.ToBig() - if headerGasTip != nil { - tipCap = new(big.Int).Set(headerGasTip) - } - - tip := new(big.Int).Sub(tx.GasFeeCap.ToBig(), baseFee) - if tip.Cmp(tipCap) > 0 { - tip.Set(tipCap) + tip := dst.Sub(tx.GasFeeCap.ToBig(), baseFee) + if tip.Cmp(tx.GasTipCap.ToBig()) > 0 { + tip.Set(tx.GasTipCap.ToBig()) } return tip.Add(tip, baseFee) } diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go index b731c773f..9754c114c 100644 --- a/core/types/tx_dynamic_fee.go +++ b/core/types/tx_dynamic_fee.go @@ -97,19 +97,13 @@ func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } func (tx *DynamicFeeTx) to() *common.Address { return tx.To } -func (tx *DynamicFeeTx) effectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { +func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { if baseFee == nil { - baseFee = common.Big0 + baseFee = big.NewInt(0) } - - tipCap := tx.GasTipCap - if headerGasTip != nil { - tipCap = new(big.Int).Set(headerGasTip) - } - - tip := new(big.Int).Sub(tx.GasFeeCap, baseFee) - if tip.Cmp(tipCap) > 0 { - tip.Set(tipCap) + tip := dst.Sub(tx.GasFeeCap, baseFee) + if tip.Cmp(tx.GasTipCap) > 0 { + tip.Set(tx.GasTipCap) } return tip.Add(tip, baseFee) } diff --git a/core/types/tx_fee_delegation.go b/core/types/tx_fee_delegation.go index 2abcc5916..fe8f1036e 100644 --- a/core/types/tx_fee_delegation.go +++ b/core/types/tx_fee_delegation.go @@ -129,19 +129,13 @@ func (tx *FeeDelegateDynamicFeeTx) rawFeePayerSignatureValues() (v, r, s *big.In return tx.FV, tx.FR, tx.FS } -func (tx *FeeDelegateDynamicFeeTx) effectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { +func (tx *FeeDelegateDynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { if baseFee == nil { - baseFee = common.Big0 + baseFee = big.NewInt(0) } - - tipCap := tx.SenderTx.GasTipCap - if headerGasTip != nil { - tipCap = new(big.Int).Set(headerGasTip) - } - - tip := new(big.Int).Sub(tx.SenderTx.GasFeeCap, baseFee) - if tip.Cmp(tipCap) > 0 { - tip.Set(tipCap) + tip := dst.Sub(tx.SenderTx.GasFeeCap, baseFee) + if tip.Cmp(tx.SenderTx.GasTipCap) > 0 { + tip.Set(tx.SenderTx.GasTipCap) } return tip.Add(tip, baseFee) } diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 4d8221a7a..257df2c65 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -104,8 +104,8 @@ func (tx *LegacyTx) value() *big.Int { return tx.Value } func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } func (tx *LegacyTx) to() *common.Address { return tx.To } -func (tx *LegacyTx) effectiveGasPrice(baseFee, headerGasTip *big.Int) *big.Int { - return new(big.Int).Set(tx.GasPrice) +func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { + return dst.Set(tx.GasPrice) } func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) { diff --git a/core/types/types_test.go b/core/types/types_test.go index 1fb386d5d..d38a9f978 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -76,6 +76,7 @@ func benchRLP(b *testing.B, encode bool) { &ReceiptForStorage{ Status: ReceiptStatusSuccessful, CumulativeGasUsed: 0x888888888, + EffectiveGasPrice: big.NewInt(10000000000), Logs: make([]*Log, 0), }, }, diff --git a/eth/api_backend.go b/eth/api_backend.go index 2eda7a96a..188e34b70 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -441,3 +441,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } + +func (b *EthAPIBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return b.eth.BlockChain().StateAt(root) +} diff --git a/eth/gasprice/anzeon.go b/eth/gasprice/anzeon.go new file mode 100644 index 000000000..e2c2e5742 --- /dev/null +++ b/eth/gasprice/anzeon.go @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright 2025 The go-stablenet Authors +// This file is part of the go-stablenet library. +// +// The go-stablenet library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-stablenet library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-stablenet library. If not, see . + +package gasprice + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" +) + +// AnzeonTipEnv manages Anzeon-specific gas tip calculation environment for transaction pool. +// It maintains state for dynamic gas tip calculations based on block headers and account authorization. +type AnzeonTipEnv struct { + config *params.ChainConfig + stateAt func(common.Hash) (*state.StateDB, error) + currentBlock *types.Header + baseFee *big.Int + signer types.Signer +} + +// NewAnzeonTipEnv creates a new AnzeonTipEnv instance for use in transaction pool. +func NewAnzeonTipEnv(config *params.ChainConfig, stateAt func(common.Hash) (*state.StateDB, error)) *AnzeonTipEnv { + return &AnzeonTipEnv{ + config: config, + stateAt: stateAt, + } +} + +// SetCurrentBlock updates the current block header and signer. +// This should be called when the blockchain head changes. +func (env *AnzeonTipEnv) SetCurrentBlock(header *types.Header) { + if header == nil { + return + } + env.currentBlock = header + env.signer = types.MakeSigner(env.config, header.Number, header.Time) +} + +// SetBaseFee updates the base fee for gas price calculations. +func (env *AnzeonTipEnv) SetBaseFee(baseFee *big.Int) { + env.baseFee = baseFee +} + +// GetBaseFee returns the current base fee. +// It returns the explicitly set base fee, or falls back to the current block's base fee. +func (env *AnzeonTipEnv) GetBaseFee() *big.Int { + if env.baseFee != nil { + return env.baseFee + } + if env.currentBlock != nil && env.currentBlock.BaseFee != nil { + return env.currentBlock.BaseFee + } + return nil +} + +// GetAnzeonTipCap returns the effective gas tip cap for a transaction in the Anzeon network. +// For unauthorized accounts, it returns the block header's gas tip. +// For authorized accounts (validators/minters), it returns the transaction's original gas tip cap. +func (env *AnzeonTipEnv) GetAnzeonTipCap(tx *types.Transaction) *big.Int { + // If environment is not fully initialized, return transaction's gas tip cap + if env.signer == nil || env.currentBlock == nil { + return tx.GasTipCap() + } + + // Get sender address + from, err := types.Sender(env.signer, tx) + if err != nil { + return tx.GasTipCap() + } + + // Check if sender is authorized by querying state + if env.stateAt != nil && env.currentBlock.Root != (common.Hash{}) { + stateDB, err := env.stateAt(env.currentBlock.Root) + if err == nil && stateDB != nil { + // For unauthorized accounts, use block header's gas tip + if !stateDB.IsAuthorized(from) && env.currentBlock.GasTip() != nil { + return env.currentBlock.GasTip() + } + } + } + + // For authorized accounts or if state is unavailable, use transaction's gas tip cap + return tx.GasTipCap() +} diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go index d657eb6d9..fc5c52f95 100644 --- a/eth/gasprice/feehistory.go +++ b/eth/gasprice/feehistory.go @@ -106,9 +106,18 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) { return } + header := bf.block.Header() + var stateReader types.StateReader + if header.Root != (common.Hash{}) { + stateReader, _ = oracle.backend.StateAt(header.Root) + } + signer := types.MakeSigner(oracle.backend.ChainConfig(), header.Number, header.Time) + atEnv := types.NewInstantAnzeonTipEnv(signer, header.BaseFee, header.GasTip(), stateReader) + sorter := make([]txGasAndReward, len(bf.block.Transactions())) for i, tx := range bf.block.Transactions() { - reward, _ := tx.EffectiveGasTip(bf.block.BaseFee()) + var reward *big.Int + reward, _ = tx.EffectiveGasTip(atEnv) sorter[i] = txGasAndReward{gasUsed: bf.receipts[i].GasUsed, reward: reward} } slices.SortStableFunc(sorter, func(a, b txGasAndReward) int { diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 1a8f0abd2..b99ece40b 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -58,6 +59,7 @@ type OracleBackend interface { PendingBlockAndReceipts() (*types.Block, types.Receipts) ChainConfig() *params.ChainConfig SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription + StateAt(root common.Hash) (*state.StateDB, error) } // Oracle recommends gas prices based on the content of recent @@ -242,24 +244,40 @@ func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit } return } + + header := block.Header() + var stateReader types.StateReader + if header.Root != (common.Hash{}) { + stateReader, _ = oracle.backend.StateAt(header.Root) + } signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number(), block.Time()) + atEnv := types.NewInstantAnzeonTipEnv(signer, header.BaseFee, header.GasTip(), stateReader) // Sort the transaction by effective tip in ascending sort. txs := block.Transactions() + + // Create a map to store tip for each transaction + tipMap := make(map[common.Hash]*big.Int) + for _, tx := range txs { + var tip *big.Int + tip, _ = tx.EffectiveGasTip(atEnv) + tipMap[tx.Hash()] = tip + } + sortedTxs := make([]*types.Transaction, len(txs)) copy(sortedTxs, txs) - baseFee := block.BaseFee() + slices.SortFunc(sortedTxs, func(a, b *types.Transaction) int { // It's okay to discard the error because a tx would never be // accepted into a block with an invalid effective tip. - tip1, _ := a.EffectiveGasTip(baseFee) - tip2, _ := b.EffectiveGasTip(baseFee) + tip1 := tipMap[a.Hash()] + tip2 := tipMap[b.Hash()] return tip1.Cmp(tip2) }) var prices []*big.Int for _, tx := range sortedTxs { - tip, _ := tx.EffectiveGasTip(baseFee) + tip := tipMap[tx.Hash()] if ignoreUnder != nil && tip.Cmp(ignoreUnder) == -1 { continue } diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 8437cac49..18d947f35 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -117,6 +118,10 @@ func (b *testBackend) teardown() { b.chain.Stop() } +func (b *testBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return b.chain.StateAt(root) +} + // newTestBackend creates a test backend. OBS: don't forget to invoke tearDown // after use, otherwise the blockchain instance will mem-leak via goroutines. func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend { diff --git a/eth/state_accessor.go b/eth/state_accessor.go index d67bd81bb..e26df0ec7 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -245,7 +245,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, if block.Header() != nil && block.Header().GasTip() != nil { headerGasTip = block.Header().GasTip() } - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) if idx == txIndex { diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 27a2dfd6d..10c17df2e 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -275,7 +275,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed if task.block.Header() != nil && task.block.Header().GasTip() != nil { headerGasTip = task.block.Header().GasTip() } - msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee(), headerGasTip, task.statedb) txctx := &Context{ BlockHash: task.block.Hash(), BlockNumber: task.block.Number(), @@ -541,7 +541,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config } var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) txContext = core.NewEVMTxContext(msg) vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) ) @@ -619,7 +619,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac headerGasTip = block.Header().GasTip() } // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -666,7 +666,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat if block.Header() != nil && block.Header().GasTip() != nil { headerGasTip = block.Header().GasTip() } - msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee(), headerGasTip, task.statedb) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -702,7 +702,7 @@ txloop: } // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { @@ -787,7 +787,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block } var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) txContext = core.NewEVMTxContext(msg) vmConf vm.Config dump *os.File diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index a88ffdf3c..1d3d058e7 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -174,7 +174,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block if block.Header() != nil && block.Header().GasTip() != nil { headerGasTip = block.Header().GasTip() } - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), headerGasTip, statedb) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), b.chain, nil) if idx == txIndex { diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 30c7948a8..7dfce0ece 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -141,7 +141,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -231,7 +231,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index a9baf26af..6d5fe597c 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -103,7 +103,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string if err != nil { return fmt.Errorf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil, nil) if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index fdd2d0cd5..bc0ed4f90 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -111,7 +111,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, nil, nil) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index af7a6a4de..18c4794f6 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -90,7 +90,7 @@ func BenchmarkTransactionTrace(b *testing.B) { //EnableReturnData: false, }) evm := vm.NewEVM(context, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer}) - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, big.NewInt(500)) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, big.NewInt(500), state.StateDB) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/ethclient/test/ethclient_test.go b/ethclient/test/ethclient_test.go index 3c387cf2d..81b751b23 100644 --- a/ethclient/test/ethclient_test.go +++ b/ethclient/test/ethclient_test.go @@ -504,13 +504,9 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) { } // SuggestGasPrice - // Note: The expected gas price is calculated as SuggestGasTipCap + BaseFee - // SuggestGasTipCap returns 100 GWei (from miner.DefaultConfig.GasPrice) - // BaseFee is dynamically calculated based on EIP-1559 mechanism: - // - Genesis block: 1 GWei (params.InitialBaseFee) - // - Block 1: Decreased to ~0.77 GWei due to no transactions (GasUsed < GasTarget) - // - Block 2: Further adjusted based on block 1's gas usage - // Total: 100 GWei + 0.77 GWei = 100.77 GWei + // Note: Returns the suggested gas price from the oracle. + // Formula: eth_gasPrice = eth_maxPriorityFeePerGas + BaseFee + // The gas price oracle samples recent blocks to determine appropriate tip. gasPrice, err := ec.SuggestGasPrice(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -520,8 +516,9 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) { } // SuggestGasTipCap - // Note: Returns the configured miner gas price (100 GWei) - // This value is set in miner.DefaultConfig.GasPrice and applied as GasTip + // Note: Returns the suggested gas tip cap (priority fee) from the oracle. + // For non-Anzeon chains, the oracle analyzes recent transaction gas prices + // from historical blocks to determine an appropriate tip value. gasTipCap, err := ec.SuggestGasTipCap(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/graphql/graphql.go b/graphql/graphql.go index e412f47ca..5c5189e03 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -375,7 +375,7 @@ func (t *Transaction) EffectiveTip(ctx context.Context) (*hexutil.Big, error) { return (*hexutil.Big)(tx.GasPrice()), nil } - tip, err := tx.EffectiveGasTip(header.BaseFee) + tip, err := tx.EffectiveGasTip(nil) // not used if err != nil { return nil, err } diff --git a/miner/ordering.go b/miner/ordering.go index bcf7af46e..b0582df8a 100644 --- a/miner/ordering.go +++ b/miner/ordering.go @@ -21,6 +21,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" @@ -36,15 +37,19 @@ type txWithMinerFee struct { // newTxWithMinerFee creates a wrapped transaction, calculating the effective // miner gasTipCap if a base fee is provided. // Returns error in case of a negative effective miner gasTipCap. -func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *uint256.Int) (*txWithMinerFee, error) { +func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee, headerTip *uint256.Int, isAuthorized bool) (*txWithMinerFee, error) { tip := new(uint256.Int).Set(tx.GasTipCap) if baseFee != nil { if tx.GasFeeCap.Cmp(baseFee) < 0 { return nil, types.ErrGasFeeCapTooLow } tip = new(uint256.Int).Sub(tx.GasFeeCap, baseFee) - if tip.Gt(tx.GasTipCap) { - tip = tx.GasTipCap + txTip := new(uint256.Int).Set(tx.GasTipCap) + if !isAuthorized && headerTip != nil && txTip.Gt(headerTip) { + tip = headerTip + } + if tip.Gt(txTip) { + tip = txTip } } return &txWithMinerFee{ @@ -54,32 +59,58 @@ func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee }, nil } -// txByPriceAndTime implements both the sort and the heap interface, making it useful -// for all at once sorting as well as individually adding and removing elements. -type txByPriceAndTime []*txWithMinerFee - -func (s txByPriceAndTime) Len() int { return len(s) } -func (s txByPriceAndTime) Less(i, j int) bool { - // If the prices are equal, use the time the transaction was first seen for - // deterministic sorting - cmp := s[i].fees.Cmp(s[j].fees) - if cmp == 0 { - return s[i].tx.Time.Before(s[j].tx.Time) +type txByPriceAndTime struct { + txs []*txWithMinerFee + anzeonEnabled bool // Cached value of chainConfig.AnzeonEnabled() to avoid repeated checks + isAuthorized map[common.Address]bool // Pre-computed authorized status for all accounts to avoid repeated checks in Less() +} + +func (s *txByPriceAndTime) Len() int { return len(s.txs) } +func (s *txByPriceAndTime) Less(i, j int) bool { + // If Anzeon is not enabled, use the original fee-based ordering + if !s.anzeonEnabled { + cmp := s.txs[i].fees.Cmp(s.txs[j].fees) + if cmp == 0 { + return s.txs[i].tx.Time.Before(s.txs[j].tx.Time) + } + return cmp > 0 + } + + // Check if accounts are authorized (using pre-computed map for performance) + iAuthorized := s.isAuthorized[s.txs[i].from] + jAuthorized := s.isAuthorized[s.txs[j].from] + + // If both are authorized or both are not authorized, use fee-based ordering within the same group + if iAuthorized == jAuthorized { + if iAuthorized { + // Both authorized: compare by fee (higher first), then by time (earlier first) + cmp := s.txs[i].fees.Cmp(s.txs[j].fees) + if cmp == 0 { + return s.txs[i].tx.Time.Before(s.txs[j].tx.Time) + } + return cmp > 0 + } else { + // Both not authorized: compare by time only (earlier first, no fee comparison) + // General accounts are ordered by FIFO regardless of fee + return s.txs[i].tx.Time.Before(s.txs[j].tx.Time) + } } - return cmp > 0 + + // If one is authorized and the other is not, authorized always comes first + return iAuthorized } -func (s txByPriceAndTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s *txByPriceAndTime) Swap(i, j int) { s.txs[i], s.txs[j] = s.txs[j], s.txs[i] } func (s *txByPriceAndTime) Push(x interface{}) { - *s = append(*s, x.(*txWithMinerFee)) + s.txs = append(s.txs, x.(*txWithMinerFee)) } func (s *txByPriceAndTime) Pop() interface{} { - old := *s + old := s.txs n := len(old) x := old[n-1] old[n-1] = nil - *s = old[0 : n-1] + s.txs = old[0 : n-1] return x } @@ -87,10 +118,12 @@ func (s *txByPriceAndTime) Pop() interface{} { // transactions in a profit-maximizing sorted order, while supporting removing // entire batches of transactions for non-executable accounts. type transactionsByPriceAndNonce struct { - txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions - heads txByPriceAndTime // Next transaction for each unique account (price heap) - signer types.Signer // Signer for the set of transactions - baseFee *uint256.Int // Current base fee + txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions + heads txByPriceAndTime // Next transaction for each unique account (price heap) + signer types.Signer // Signer for the set of transactions + baseFee *uint256.Int // Current base fee + headerTip *uint256.Int + isAuthorizedMap map[common.Address]bool } // newTransactionsByPriceAndNonce creates a transaction set that can retrieve @@ -98,48 +131,63 @@ type transactionsByPriceAndNonce struct { // // Note, the input map is reowned so the caller should not interact any more with // if after providing it to the constructor. -func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce { +func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int, headerTip *big.Int, anzeonEnabled bool, stateDB *state.StateDB) *transactionsByPriceAndNonce { // Convert the basefee from header format to uint256 format var baseFeeUint *uint256.Int if baseFee != nil { baseFeeUint = uint256.MustFromBig(baseFee) } // Initialize a price and received time based heap with the head transactions - heads := make(txByPriceAndTime, 0, len(txs)) + isAuthorizedMap := make(map[common.Address]bool, len(txs)) + if anzeonEnabled { + for from := range txs { + if stateDB != nil { + isAuthorizedMap[from] = stateDB.IsAuthorized(from) + } + } + } + + heads := txByPriceAndTime{ + txs: make([]*txWithMinerFee, 0, len(txs)), + anzeonEnabled: anzeonEnabled, + isAuthorized: isAuthorizedMap, + } for from, accTxs := range txs { - wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFeeUint) + wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFeeUint, uint256.MustFromBig(headerTip), isAuthorizedMap[from]) if err != nil { delete(txs, from) continue } - heads = append(heads, wrapped) + heads.txs = append(heads.txs, wrapped) txs[from] = accTxs[1:] } heap.Init(&heads) // Assemble and return the transaction set return &transactionsByPriceAndNonce{ - txs: txs, - heads: heads, - signer: signer, - baseFee: baseFeeUint, + txs: txs, + heads: heads, + signer: signer, + baseFee: baseFeeUint, + headerTip: uint256.MustFromBig(headerTip), + isAuthorizedMap: isAuthorizedMap, } } // Peek returns the next transaction by price. func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *uint256.Int) { - if len(t.heads) == 0 { + if len(t.heads.txs) == 0 { return nil, nil } - return t.heads[0].tx, t.heads[0].fees + return t.heads.txs[0].tx, t.heads.txs[0].fees } // Shift replaces the current best head with the next one from the same account. func (t *transactionsByPriceAndNonce) Shift() { - acc := t.heads[0].from + acc := t.heads.txs[0].from if txs, ok := t.txs[acc]; ok && len(txs) > 0 { - if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee); err == nil { - t.heads[0], t.txs[acc] = wrapped, txs[1:] + if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee, t.headerTip, t.isAuthorizedMap[acc]); err == nil { + t.heads.txs[0], t.txs[acc] = wrapped, txs[1:] heap.Fix(&t.heads, 0) return } @@ -157,10 +205,10 @@ func (t *transactionsByPriceAndNonce) Pop() { // Empty returns if the price heap is empty. It can be used to check it simpler // than calling peek and checking for nil return. func (t *transactionsByPriceAndNonce) Empty() bool { - return len(t.heads) == 0 + return len(t.heads.txs) == 0 } // Clear removes the entire content of the heap. func (t *transactionsByPriceAndNonce) Clear() { - t.heads, t.txs = nil, nil + t.heads.txs, t.txs = nil, nil } diff --git a/miner/ordering_test.go b/miner/ordering_test.go index 3587a835c..8e2dfd92e 100644 --- a/miner/ordering_test.go +++ b/miner/ordering_test.go @@ -24,12 +24,59 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" ) +var ( + // Test accounts for authorized account tests + testAuthorizedKey1, _ = crypto.GenerateKey() + testAuthorizedAddr1 = crypto.PubkeyToAddress(testAuthorizedKey1.PublicKey) + testAuthorizedKey2, _ = crypto.GenerateKey() + testAuthorizedAddr2 = crypto.PubkeyToAddress(testAuthorizedKey2.PublicKey) + testAuthorizedKey3, _ = crypto.GenerateKey() + testAuthorizedAddr3 = crypto.PubkeyToAddress(testAuthorizedKey3.PublicKey) + + // Test accounts for normal account tests + testNormalKey1, _ = crypto.GenerateKey() + testNormalAddr1 = crypto.PubkeyToAddress(testNormalKey1.PublicKey) + testNormalKey2, _ = crypto.GenerateKey() + testNormalAddr2 = crypto.PubkeyToAddress(testNormalKey2.PublicKey) + testNormalKey3, _ = crypto.GenerateKey() + testNormalAddr3 = crypto.PubkeyToAddress(testNormalKey3.PublicKey) + + // Pre-configured stateDB for tests + testStateDB = setupTestStateDB() +) + +// setupTestStateDB creates a stateDB for testing and sets up accounts. +func setupTestStateDB() *state.StateDB { + // Create stateDB for testing (prepared for future StateAccount.Extra field usage) + db := rawdb.NewMemoryDatabase() + sdb := state.NewDatabase(db) + stateDB, _ := state.New(types.EmptyRootHash, sdb, nil) + + // Include all test accounts in stateDB + allAddrs := []common.Address{ + testAuthorizedAddr1, testAuthorizedAddr2, testAuthorizedAddr3, + testNormalAddr1, testNormalAddr2, testNormalAddr3, + } + for _, addr := range allAddrs { + stateDB.CreateAccount(addr) + } + + if stateDB != nil { + stateDB.SetAuthorized(testAuthorizedAddr1) + stateDB.SetAuthorized(testAuthorizedAddr2) + stateDB.SetAuthorized(testAuthorizedAddr3) + } + return stateDB +} + func TestTransactionPriceNonceSortLegacy(t *testing.T) { t.Parallel() testTransactionPriceNonceSort(t, nil) @@ -42,6 +89,25 @@ func TestTransactionPriceNonceSort1559(t *testing.T) { testTransactionPriceNonceSort(t, big.NewInt(50)) } +type noAnzeonTIpEnv struct { + baseFee *big.Int +} + +func (natEnv *noAnzeonTIpEnv) GetBaseFee() *big.Int { + return natEnv.baseFee +} + +func (natEnv *noAnzeonTIpEnv) GetAnzeonTipCap(tx *types.Transaction) *big.Int { + return tx.GasTipCap() +} + +func (natEnv *noAnzeonTIpEnv) SetCurrentBlock(header *types.Header) { +} + +func (natEnv *noAnzeonTIpEnv) SetBaseFee(baseFee *big.Int) { + natEnv.baseFee = baseFee +} + // Tests that transactions can be correctly sorted according to their price in // decreasing order, but at the same time with increasing nonces when issued by // the same account. @@ -102,7 +168,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) { expectedCount += count } // Sort the transactions and cross check the nonce ordering - txset := newTransactionsByPriceAndNonce(signer, groups, baseFee) + txset := newTransactionsByPriceAndNonce(signer, groups, baseFee, nil, false, nil) txs := types.Transactions{} for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { @@ -112,6 +178,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) { if len(txs) != expectedCount { t.Errorf("expected %d transactions, found %d", expectedCount, len(txs)) } + anzeonTIpEnv := &noAnzeonTIpEnv{baseFee: baseFee} for i, txi := range txs { fromi, _ := types.Sender(signer, txi) @@ -126,8 +193,8 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) { if i+1 < len(txs) { next := txs[i+1] fromNext, _ := types.Sender(signer, next) - tip, err := txi.EffectiveGasTip(baseFee) - nextTip, nextErr := next.EffectiveGasTip(baseFee) + tip, err := txi.EffectiveGasTip(anzeonTIpEnv) + nextTip, nextErr := next.EffectiveGasTip(anzeonTIpEnv) if err != nil || nextErr != nil { t.Errorf("error calculating effective tip: %v, %v", err, nextErr) } @@ -168,7 +235,7 @@ func TestTransactionTimeSort(t *testing.T) { }) } // Sort the transactions and cross check the nonce ordering - txset := newTransactionsByPriceAndNonce(signer, groups, nil) + txset := newTransactionsByPriceAndNonce(signer, groups, nil, nil, false, nil) txs := types.Transactions{} for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { @@ -194,3 +261,722 @@ func TestTransactionTimeSort(t *testing.T) { } } } + +// TestAuthorizedAccountPriority tests the priority ordering for authorized accounts +func TestAuthorizedAccountPriority(t *testing.T) { + t.Parallel() + + signer := types.LatestSignerForChainID(common.Big1) + + // Use pre-configured stateDB with authorized accounts + stateDB := testStateDB + + groups := map[common.Address][]*txpool.LazyTransaction{} + + // Authorized account 1 + tx1, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(20), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testAuthorizedKey1) + tx1.SetTime(time.Unix(4, 0)) + groups[testAuthorizedAddr1] = []*txpool.LazyTransaction{{ + Hash: tx1.Hash(), + Tx: tx1, + Time: tx1.Time(), + GasFeeCap: uint256.MustFromBig(tx1.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx1.GasTipCap()), + Gas: tx1.Gas(), + BlobGas: tx1.BlobGas(), + }} + + // Authorized account 2 + tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(15), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testAuthorizedKey2) + tx2.SetTime(time.Unix(3, 0)) + groups[testAuthorizedAddr2] = []*txpool.LazyTransaction{{ + Hash: tx2.Hash(), + Tx: tx2, + Time: tx2.Time(), + GasFeeCap: uint256.MustFromBig(tx2.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx2.GasTipCap()), + Gas: tx2.Gas(), + BlobGas: tx2.BlobGas(), + }} + + // Normal account 1 + tx3, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(200), + GasTipCap: big.NewInt(100), + Data: nil, + }), signer, testNormalKey1) + tx3.SetTime(time.Unix(2, 0)) + groups[testNormalAddr1] = []*txpool.LazyTransaction{{ + Hash: tx3.Hash(), + Tx: tx3, + Time: tx3.Time(), + GasFeeCap: uint256.MustFromBig(tx3.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx3.GasTipCap()), + Gas: tx3.Gas(), + BlobGas: tx3.BlobGas(), + }} + + // Normal account 2 + tx4, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(15), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey2) + tx4.SetTime(time.Unix(1, 0)) + groups[testNormalAddr2] = []*txpool.LazyTransaction{{ + Hash: tx4.Hash(), + Tx: tx4, + Time: tx4.Time(), + GasFeeCap: uint256.MustFromBig(tx4.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx4.GasTipCap()), + Gas: tx4.Gas(), + BlobGas: tx4.BlobGas(), + }} + + txset := newTransactionsByPriceAndNonce(signer, groups, big.NewInt(0), nil, true, stateDB) + + txs := types.Transactions{} + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txs = append(txs, tx.Tx) + txset.Shift() + } + + // fee order: tx3 > tx1 > tx4 = tx2 + // time order: tx4 > tx3 > tx2 > tx1 + // tx1(testAuthorizedAddr1), tx2(testAuthorizedAddr2) : Authorized account + // tx3(testNormalAddr1),tx4(testNormalAddr2) : Normal account + + // Expected order: + // tx1 > tx2 > tx4 > tx3 + if len(txs) != 4 { + t.Fatalf("expected 4 transactions, found %d", len(txs)) + } + + from1, _ := types.Sender(signer, txs[0]) + from2, _ := types.Sender(signer, txs[1]) + from3, _ := types.Sender(signer, txs[2]) + from4, _ := types.Sender(signer, txs[3]) + + // First two should be authorized accounts (ordered by fee) + if from1 != testAuthorizedAddr1 { + t.Errorf("expected first tx from authorized account 1, got %x", from1) + } + if from2 != testAuthorizedAddr2 { + t.Errorf("expected second tx from authorized account 2, got %x", from2) + } + + // Last two should be normal accounts (ordered by time/FIFO) + if from3 != testNormalAddr2 { + t.Errorf("expected third tx from normal account 1, got %x", from3) + } + if from4 != testNormalAddr1 { + t.Errorf("expected fourth tx from normal account 2, got %x", from4) + } +} + +// TestAuthorizedAccountPrioritySameFee tests authorized accounts with same fee (should use FIFO) +func TestAuthorizedAccountPrioritySameFee(t *testing.T) { + t.Parallel() + + signer := types.LatestSignerForChainID(common.Big1) + + // Use pre-configured stateDB with authorized accounts + stateDB := testStateDB + + groups := map[common.Address][]*txpool.LazyTransaction{} + + // Authorized account 1 - same fee + tx1, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(20), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testAuthorizedKey1) + tx1.SetTime(time.Unix(1, 0)) + groups[testAuthorizedAddr1] = []*txpool.LazyTransaction{{ + Hash: tx1.Hash(), + Tx: tx1, + Time: tx1.Time(), + GasFeeCap: uint256.MustFromBig(tx1.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx1.GasTipCap()), + Gas: tx1.Gas(), + BlobGas: tx1.BlobGas(), + }} + + // Authorized account 2 - same fee + tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(20), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testAuthorizedKey2) + tx2.SetTime(time.Unix(3, 0)) + groups[testAuthorizedAddr2] = []*txpool.LazyTransaction{{ + Hash: tx2.Hash(), + Tx: tx2, + Time: tx2.Time(), + GasFeeCap: uint256.MustFromBig(tx2.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx2.GasTipCap()), + Gas: tx2.Gas(), + BlobGas: tx2.BlobGas(), + }} + + // Authorized account 3 - same fee + tx3, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(20), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testAuthorizedKey3) + tx3.SetTime(time.Unix(2, 0)) + groups[testAuthorizedAddr3] = []*txpool.LazyTransaction{{ + Hash: tx3.Hash(), + Tx: tx3, + Time: tx3.Time(), + GasFeeCap: uint256.MustFromBig(tx3.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx3.GasTipCap()), + Gas: tx3.Gas(), + BlobGas: tx3.BlobGas(), + }} + + txset := newTransactionsByPriceAndNonce(signer, groups, big.NewInt(0), nil, true, stateDB) + + txs := types.Transactions{} + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txs = append(txs, tx.Tx) + txset.Shift() + } + + // fee : same for all authorized accounts + // time order: tx1 > tx3 > tx2 + + // Expected order: + // tx1 > tx3 > tx2 + if len(txs) != 3 { + t.Fatalf("expected 3 transactions, found %d", len(txs)) + } + + from1, _ := types.Sender(signer, txs[0]) + from2, _ := types.Sender(signer, txs[1]) + from3, _ := types.Sender(signer, txs[2]) + + // Should be ordered by time (FIFO) when fees are equal + if from1 != testAuthorizedAddr1 { + t.Errorf("expected first tx from authorized account 1, got %x", from1) + } + if from2 != testAuthorizedAddr3 { + t.Errorf("expected second tx from authorized account 3, got %x", from2) + } + if from3 != testAuthorizedAddr2 { + t.Errorf("expected third tx from authorized account 2, got %x", from3) + } +} + +// TestNotAuthorizedFIFO tests that normal accounts are ordered by FIFO regardless of fee +func TestNotAuthorizedFIFO(t *testing.T) { + t.Parallel() + + signer := types.LatestSignerForChainID(common.Big1) + + // Use pre-configured stateDB + stateDB := testStateDB + + groups := map[common.Address][]*txpool.LazyTransaction{} + + // Normal account 1 + tx1, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(30), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testNormalKey1) + tx1.SetTime(time.Unix(2, 0)) + groups[testNormalAddr1] = []*txpool.LazyTransaction{{ + Hash: tx1.Hash(), + Tx: tx1, + Time: tx1.Time(), + GasFeeCap: uint256.MustFromBig(tx1.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx1.GasTipCap()), + Gas: tx1.Gas(), + BlobGas: tx1.BlobGas(), + }} + + // Normal account 2 + tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(40), + GasTipCap: big.NewInt(20), + Data: nil, + }), signer, testNormalKey2) + tx2.SetTime(time.Unix(3, 0)) + groups[testNormalAddr2] = []*txpool.LazyTransaction{{ + Hash: tx2.Hash(), + Tx: tx2, + Time: tx2.Time(), + GasFeeCap: uint256.MustFromBig(tx2.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx2.GasTipCap()), + Gas: tx2.Gas(), + BlobGas: tx2.BlobGas(), + }} + + // Normal account 3 + tx3, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey3) + tx3.SetTime(time.Unix(1, 0)) + groups[testNormalAddr3] = []*txpool.LazyTransaction{{ + Hash: tx3.Hash(), + Tx: tx3, + Time: tx3.Time(), + GasFeeCap: uint256.MustFromBig(tx3.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx3.GasTipCap()), + Gas: tx3.Gas(), + BlobGas: tx3.BlobGas(), + }} + + txset := newTransactionsByPriceAndNonce(signer, groups, big.NewInt(0), nil, true, stateDB) + + txs := types.Transactions{} + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txs = append(txs, tx.Tx) + txset.Shift() + } + + // fee order : Normal account is not considered, only authorized accounts are considered for fee ordering in anzeon enabled mode + // time order: tx3 > tx1 > tx2 + + // Expected order: + // tx3 > tx1 > tx2 + if len(txs) != 3 { + t.Fatalf("expected 3 transactions, found %d", len(txs)) + } + + from1, _ := types.Sender(signer, txs[0]) + from2, _ := types.Sender(signer, txs[1]) + from3, _ := types.Sender(signer, txs[2]) + + // Should be ordered by time (FIFO) regardless of fee in anzeon enabled mode + if from1 != testNormalAddr3 { + t.Errorf("expected first tx from normal account 3, got %x", from1) + } + if from2 != testNormalAddr1 { + t.Errorf("expected second tx from normal account 1, got %x", from2) + } + if from3 != testNormalAddr2 { + t.Errorf("expected third tx from normal account 2, got %x", from3) + } +} + +// TestAnzeonDisabledAndFIFO tests that normal accounts are ordered by FIFO regardless of fee +func TestAnzeonDisabledAndFIFO(t *testing.T) { + t.Parallel() + + signer := types.LatestSignerForChainID(common.Big1) + + groups := map[common.Address][]*txpool.LazyTransaction{} + + // Normal account 1 + tx1, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey1) + tx1.SetTime(time.Unix(3, 0)) + groups[testNormalAddr1] = []*txpool.LazyTransaction{{ + Hash: tx1.Hash(), + Tx: tx1, + Time: tx1.Time(), + GasFeeCap: uint256.MustFromBig(tx1.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx1.GasTipCap()), + Gas: tx1.Gas(), + BlobGas: tx1.BlobGas(), + }} + + // Normal account 2 + tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey2) + tx2.SetTime(time.Unix(1, 0)) + groups[testNormalAddr2] = []*txpool.LazyTransaction{{ + Hash: tx2.Hash(), + Tx: tx2, + Time: tx2.Time(), + GasFeeCap: uint256.MustFromBig(tx2.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx2.GasTipCap()), + Gas: tx2.Gas(), + BlobGas: tx2.BlobGas(), + }} + + // Normal account 3 + tx3, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey3) + tx3.SetTime(time.Unix(2, 0)) + groups[testNormalAddr3] = []*txpool.LazyTransaction{{ + Hash: tx3.Hash(), + Tx: tx3, + Time: tx3.Time(), + GasFeeCap: uint256.MustFromBig(tx3.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx3.GasTipCap()), + Gas: tx3.Gas(), + BlobGas: tx3.BlobGas(), + }} + + txset := newTransactionsByPriceAndNonce(signer, groups, big.NewInt(0), nil, false, nil) + + txs := types.Transactions{} + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txs = append(txs, tx.Tx) + txset.Shift() + } + + // fee order : same for all normal accounts + // time order: tx2 > tx3 > tx1 + + // Expected order: + // tx2 > tx3 > tx1 + if len(txs) != 3 { + t.Fatalf("expected 3 transactions, found %d", len(txs)) + } + + from1, _ := types.Sender(signer, txs[0]) + from2, _ := types.Sender(signer, txs[1]) + from3, _ := types.Sender(signer, txs[2]) + + // Should be ordered by time (FIFO) when fees are equal + if from1 != testNormalAddr2 { + t.Errorf("expected first tx from normal account 2, got %x", from1) + } + if from2 != testNormalAddr3 { + t.Errorf("expected second tx from normal account 3, got %x", from2) + } + if from3 != testNormalAddr1 { + t.Errorf("expected third tx from normal account 1, got %x", from3) + } +} + +// TestAnzeonDisabledAndHigherFeeFirst tests that when Anzeon is disabled, original fee-based ordering is used and higher fee first +func TestAnzeonDisabledAndHigherFeeFirst(t *testing.T) { + t.Parallel() + + signer := types.LatestSignerForChainID(common.Big1) + + groups := map[common.Address][]*txpool.LazyTransaction{} + + // Account 1 + tx1, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(5), + Data: nil, + }), signer, testNormalKey1) + tx1.SetTime(time.Unix(1, 0)) + groups[testNormalAddr1] = []*txpool.LazyTransaction{{ + Hash: tx1.Hash(), + Tx: tx1, + Time: tx1.Time(), + GasFeeCap: uint256.MustFromBig(tx1.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx1.GasTipCap()), + Gas: tx1.Gas(), + BlobGas: tx1.BlobGas(), + }} + + // Account 2 + tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(30), + GasTipCap: big.NewInt(20), + Data: nil, + }), signer, testNormalKey2) + tx1.SetTime(time.Unix(2, 0)) + groups[testNormalAddr2] = []*txpool.LazyTransaction{{ + Hash: tx2.Hash(), + Tx: tx2, + Time: tx2.Time(), + GasFeeCap: uint256.MustFromBig(tx2.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx2.GasTipCap()), + Gas: tx2.Gas(), + BlobGas: tx2.BlobGas(), + }} + + // Account 3 + tx3, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: 0, + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: big.NewInt(25), + GasTipCap: big.NewInt(10), + Data: nil, + }), signer, testNormalKey3) + tx3.SetTime(time.Unix(3, 0)) + groups[testNormalAddr3] = []*txpool.LazyTransaction{{ + Hash: tx3.Hash(), + Tx: tx3, + Time: tx3.Time(), + GasFeeCap: uint256.MustFromBig(tx3.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx3.GasTipCap()), + Gas: tx3.Gas(), + BlobGas: tx3.BlobGas(), + }} + + txset := newTransactionsByPriceAndNonce(signer, groups, big.NewInt(0), nil, false, nil) + + txs := types.Transactions{} + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txs = append(txs, tx.Tx) + txset.Shift() + } + + // fee order : tx2 > tx3 > tx1 + // time order: tx1 > tx2 > tx3 + + // Expected order: + // tx2 > tx3 > tx1 + if len(txs) != 3 { + t.Fatalf("expected 3 transactions, found %d", len(txs)) + } + + from1, _ := types.Sender(signer, txs[0]) + from2, _ := types.Sender(signer, txs[1]) + from3, _ := types.Sender(signer, txs[2]) + + // Should be ordered by fee (higher first) when Anzeon is disabled + if from1 != testNormalAddr2 { + t.Errorf("expected first tx from account 2, got %x", from1) + } + if from2 != testNormalAddr3 { + t.Errorf("expected second tx from account 3, got %x", from2) + } + if from3 != testNormalAddr1 { + t.Errorf("expected third tx from account 1, got %x", from3) + } +} + +// Benchmark helpers +func generateTransactions(numAccounts, txsPerAccount int, authorizedRatio float64, rng *rand.Rand) (map[common.Address][]*txpool.LazyTransaction, *state.StateDB) { + signer := types.LatestSignerForChainID(common.Big1) + db := rawdb.NewMemoryDatabase() + sdb := state.NewDatabase(db) + stateDB, _ := state.New(types.EmptyRootHash, sdb, nil) + + groups := make(map[common.Address][]*txpool.LazyTransaction) + authorizedCount := int(float64(numAccounts) * authorizedRatio) + + for i := 0; i < numAccounts; i++ { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + stateDB.CreateAccount(addr) + + isAuthorized := i < authorizedCount + if isAuthorized { + stateDB.SetAuthorized(addr) + } + + for j := 0; j < txsPerAccount; j++ { + gasFeeCap := big.NewInt(int64(10 + rng.Intn(100))) + gasTipCap := big.NewInt(int64(1 + rng.Intn(int(gasFeeCap.Int64())))) + txTime := time.Unix(int64(rng.Intn(1000000)), 0) + + tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ + Nonce: uint64(j), + To: &common.Address{}, + Value: big.NewInt(100), + Gas: 100, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: nil, + }), signer, key) + tx.SetTime(txTime) + + groups[addr] = append(groups[addr], &txpool.LazyTransaction{ + Hash: tx.Hash(), + Tx: tx, + Time: tx.Time(), + GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()), + GasTipCap: uint256.MustFromBig(tx.GasTipCap()), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), + }) + } + } + + return groups, stateDB +} + +func benchmarkOrdering(b *testing.B, numAccounts, txsPerAccount int, authorizedRatio float64, anzeonEnabled bool) { + // Generate transactions once before starting the timer + rng := rand.New(rand.NewSource(42)) + groups, stateDB := generateTransactions(numAccounts, txsPerAccount, authorizedRatio, rng) + signer := types.LatestSignerForChainID(common.Big1) + baseFee := big.NewInt(0) + + // Prepare groups copy template (will be copied in each iteration) + groupsTemplate := make(map[common.Address][]*txpool.LazyTransaction) + for addr, txs := range groups { + txsCopy := make([]*txpool.LazyTransaction, len(txs)) + copy(txsCopy, txs) + groupsTemplate[addr] = txsCopy + } + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + // Recreate groups for each iteration + groupsCopy := make(map[common.Address][]*txpool.LazyTransaction) + for addr, txs := range groupsTemplate { + txsCopy := make([]*txpool.LazyTransaction, len(txs)) + copy(txsCopy, txs) + groupsCopy[addr] = txsCopy + } + + txset := newTransactionsByPriceAndNonce(signer, groupsCopy, baseFee, nil, anzeonEnabled, stateDB) + + // Consume all transactions to measure full sorting performance + for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { + txset.Shift() + } + } +} + +// Benchmark_10Accounts_10Txs benchmarks ordering with 10 accounts, 10 transactions per account +// Compares different account types and configurations +func Benchmark_10Accounts_10Txs(b *testing.B) { + b.Run("AuthorizedOnly", func(b *testing.B) { + benchmarkOrdering(b, 10, 10, 1.0, true) + }) + b.Run("NormalOnly", func(b *testing.B) { + benchmarkOrdering(b, 10, 10, 0.0, true) + }) + b.Run("Mixed_50Percent", func(b *testing.B) { + benchmarkOrdering(b, 10, 10, 0.5, true) + }) + b.Run("AnzeonDisabled", func(b *testing.B) { + benchmarkOrdering(b, 10, 10, 0.5, false) + }) +} + +// Benchmark_50Accounts_10Txs benchmarks ordering with 50 accounts, 10 transactions per account +// Compares different account types and configurations +func Benchmark_50Accounts_10Txs(b *testing.B) { + b.Run("AuthorizedOnly", func(b *testing.B) { + benchmarkOrdering(b, 50, 10, 1.0, true) + }) + b.Run("NormalOnly", func(b *testing.B) { + benchmarkOrdering(b, 50, 10, 0.0, true) + }) + b.Run("Mixed_50Percent", func(b *testing.B) { + benchmarkOrdering(b, 50, 10, 0.5, true) + }) + b.Run("AnzeonDisabled", func(b *testing.B) { + benchmarkOrdering(b, 50, 10, 0.5, false) + }) +} + +// Benchmark_100Accounts_10Txs benchmarks ordering with 100 accounts, 10 transactions per account +// Compares different account types and configurations +func Benchmark_100Accounts_10Txs(b *testing.B) { + b.Run("AuthorizedOnly", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 1.0, true) + }) + b.Run("NormalOnly", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 0.0, true) + }) + b.Run("Mixed_50Percent", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 0.5, true) + }) + b.Run("Mixed_20Percent", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 0.2, true) + }) + b.Run("Mixed_80Percent", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 0.8, true) + }) + b.Run("AnzeonDisabled", func(b *testing.B) { + benchmarkOrdering(b, 100, 10, 0.5, false) + }) +} + +// Benchmark_100Accounts_50Txs benchmarks ordering with 100 accounts, 50 transactions per account +// Compares different account types and configurations +func Benchmark_100Accounts_50Txs(b *testing.B) { + b.Run("AuthorizedOnly", func(b *testing.B) { + benchmarkOrdering(b, 100, 50, 1.0, true) + }) + b.Run("NormalOnly", func(b *testing.B) { + benchmarkOrdering(b, 100, 50, 0.0, true) + }) + b.Run("Mixed_50Percent", func(b *testing.B) { + benchmarkOrdering(b, 100, 50, 0.5, true) + }) + b.Run("AnzeonDisabled", func(b *testing.B) { + benchmarkOrdering(b, 100, 50, 0.5, false) + }) +} diff --git a/miner/worker.go b/miner/worker.go index ca42f7c1f..2458ba59f 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -381,7 +381,6 @@ func (w *worker) setGasTipUnsafe(tip *big.Int) bool { } w.tip = uint256.MustFromBig(tip) - // TODO: This part will be refactored to implement Minter transaction prioritization. // Update txPool's gas tip to filter pending transactions accordingly w.eth.TxPool().SetGasTip(tip) @@ -731,8 +730,9 @@ func (w *worker) mainLoop() { BlobGas: tx.BlobGas(), }) } - plainTxs := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) // Mixed bag of everrything, yolo - blobTxs := newTransactionsByPriceAndNonce(w.current.signer, nil, w.current.header.BaseFee) // Empty bag, don't bother optimising + anzeonEnabled := w.chainConfig.AnzeonEnabled() + plainTxs := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee, w.current.header.GasTip(), anzeonEnabled, w.current.state) // Mixed bag of everrything, yolo + blobTxs := newTransactionsByPriceAndNonce(w.current.signer, nil, w.current.header.BaseFee, w.current.header.GasTip(), anzeonEnabled, w.current.state) // Empty bag, don't bother optimising tcount := w.current.tcount w.commitTransactions(w.current, plainTxs, blobTxs, nil) @@ -1236,6 +1236,7 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err filter := txpool.PendingFilter{ MinTip: tip, } + filter.NewHeader = env.header if env.header.BaseFee != nil { filter.BaseFee = uint256.MustFromBig(env.header.BaseFee) } @@ -1263,17 +1264,18 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err } } // Fill the block with all available pending transactions. + anzeonEnabled := w.chainConfig.AnzeonEnabled() if len(localPlainTxs) > 0 || len(localBlobTxs) > 0 { - plainTxs := newTransactionsByPriceAndNonce(env.signer, localPlainTxs, env.header.BaseFee) - blobTxs := newTransactionsByPriceAndNonce(env.signer, localBlobTxs, env.header.BaseFee) + plainTxs := newTransactionsByPriceAndNonce(env.signer, localPlainTxs, env.header.BaseFee, env.header.GasTip(), anzeonEnabled, env.state) + blobTxs := newTransactionsByPriceAndNonce(env.signer, localBlobTxs, env.header.BaseFee, env.header.GasTip(), anzeonEnabled, env.state) if err := w.commitTransactions(env, plainTxs, blobTxs, interrupt); err != nil { return err } } if len(remotePlainTxs) > 0 || len(remoteBlobTxs) > 0 { - plainTxs := newTransactionsByPriceAndNonce(env.signer, remotePlainTxs, env.header.BaseFee) - blobTxs := newTransactionsByPriceAndNonce(env.signer, remoteBlobTxs, env.header.BaseFee) + plainTxs := newTransactionsByPriceAndNonce(env.signer, remotePlainTxs, env.header.BaseFee, env.header.GasTip(), anzeonEnabled, env.state) + blobTxs := newTransactionsByPriceAndNonce(env.signer, remoteBlobTxs, env.header.BaseFee, env.header.GasTip(), anzeonEnabled, env.state) if err := w.commitTransactions(env, plainTxs, blobTxs, interrupt); err != nil { return err @@ -1308,7 +1310,7 @@ func (w *worker) generateWork(params *generateParams) *newPayloadResult { } return &newPayloadResult{ block: block, - fees: totalFees(w.chainConfig, block, work.receipts), + fees: totalFees(w.chainConfig, block, work.receipts, work.state), sidecars: work.sidecars, } } @@ -1404,7 +1406,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti if !w.isTTDReached(block.Header()) { select { case w.taskCh <- &task{receipts: env.receipts, state: env.state, block: block, createdAt: time.Now()}: - fees := totalFees(w.chainConfig, block, env.receipts) + fees := totalFees(w.chainConfig, block, env.receipts, env.state) feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether)) log.Info("Commit new sealing work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()), "txs", env.tcount, "gas", block.GasUsed(), "fees", feesInEther, @@ -1465,19 +1467,16 @@ func copyReceipts(receipts []*types.Receipt) []*types.Receipt { } // totalFees computes total consumed miner fees in Wei. Block transactions and receipts have to have the same order. -func totalFees(c *params.ChainConfig, block *types.Block, receipts []*types.Receipt) *big.Int { +func totalFees(c *params.ChainConfig, block *types.Block, receipts []*types.Receipt, stateReader types.StateReader) *big.Int { feesWei := new(big.Int) + signer := types.MakeSigner(c, block.Number(), block.Time()) + anzeonTipEnv := types.NewInstantAnzeonTipEnv(signer, block.BaseFee(), block.Header().GasTip(), stateReader) for i, tx := range block.Transactions() { - var minerFee *big.Int + minerFee, _ := tx.EffectiveGasTip(anzeonTipEnv) + // When Anzeon is enabled, the baseFee is not burned. + // Instead, it is rewarded to the miner, making minerFee = baseFee + tip if c.AnzeonEnabled() { - // TODO: EffectiveGasPrice will be removed and replaced with the updated EffectiveGasTip function - var headerGasTip *big.Int - if block.Header() != nil && block.Header().GasTip() != nil { - headerGasTip = block.Header().GasTip() - } - minerFee = tx.EffectiveGasPrice(block.BaseFee(), headerGasTip) - } else { - minerFee, _ = tx.EffectiveGasTip(block.BaseFee()) + minerFee = minerFee.Add(minerFee, block.BaseFee()) } feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), minerFee)) }