{"url":"https://api.github.com/repos/paradigmxyz/reth/compare/f211aacf551afbf707b7fb6a40d17c8d2264110e...43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","html_url":"https://github.com/paradigmxyz/reth/compare/f211aacf551afbf707b7fb6a40d17c8d2264110e...43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","permalink_url":"https://github.com/paradigmxyz/reth/compare/paradigmxyz:f211aac...paradigmxyz:43c2c6c","diff_url":"https://github.com/paradigmxyz/reth/compare/f211aacf551afbf707b7fb6a40d17c8d2264110e...43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a.diff","patch_url":"https://github.com/paradigmxyz/reth/compare/f211aacf551afbf707b7fb6a40d17c8d2264110e...43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a.patch","base_commit":{"sha":"f211aacf551afbf707b7fb6a40d17c8d2264110e","node_id":"C_kwDOIAWIw9oAKGYyMTFhYWNmNTUxYWZiZjcwN2I3ZmI2YTQwZDE3YzhkMjI2NDExMGU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-11-22T00:07:04Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2024-11-22T00:07:04Z"},"message":"chore: rm tx alias re-export (#12762)","tree":{"sha":"41d06c71dccb539a1299618317650167b9255a25","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/41d06c71dccb539a1299618317650167b9255a25"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f211aacf551afbf707b7fb6a40d17c8d2264110e","comment_count":0,"verification":{"verified":true,"reason":"valid","signature":"-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJnP8soCRC1aQ7uu5UhlAAAFXkQAEOJcwJ6fXL2D9ZcTFZ6zcIc\nLd51FeQipQuMRPHrX/wtjeLUeZFZFlqhC4cJT3eQgxPi5G6HIVPEN66VzD7VYdrs\nXcQSPdO5K0AHn2FsoC6FXqkvYSw4NbnsWOfnoa1HqkMd7W0f6tWm9a/Y9/VV+1Nc\nzYH2t+1lCniYYySAsKKlKFCE8wC4mCJ8TVS18x/pyBamfUBH7nJsNg4D2YmUeGrM\nXa7XQKEuIhXUzpW2h6I15MZhQ943rBn/n+wASa9wbXGn4hc1UAyxXlZm1BgEnOUO\n1KS8+mjaidWlhKu+sMa5XDKJ29qstZAucKl0rMfoNAh2DhRqjgWdAjVuWU6loWVa\najF9EjdPq8yt4r6P1as+lNSzZ/5tEM4sl1WqNZT2SWnz/hX5MFgNuGpAcAYEZjSg\nH9brRA+347tw9BloernG8m/GTaPJUiNYpcvN85mRLBt4rD56B9xgxVCydmQKd0j0\n0Aq3xs46+m0TGyZlnzPR1e4EJ+06dGUM9X606kjhr0NNOnuQgLzs+c0gbquaMvFZ\nvFbQ0CYvylyB2v7miIlFwc/IvIvzb+6+5MeuAtyc/cg6iP3ks7/AOetuM3bDL0K/\nhmNXfrHtrEeNWns++sY0ZTgpDBabOUTxYcsgo1bN45pUfLpOCFKRclSljRnNmdLq\nyVD0RJ37Cb3tOOCHglJg\n=0fXL\n-----END PGP SIGNATURE-----\n","payload":"tree 41d06c71dccb539a1299618317650167b9255a25\nparent 0eaef1f1dcbe229b5964cf1622b3018b4a1f80b9\nauthor Matthias Seitz <matthias.seitz@outlook.de> 1732234024 +0100\ncommitter GitHub <noreply@github.com> 1732234024 +0100\n\nchore: rm tx alias re-export (#12762)\n\n","verified_at":"2024-11-22T00:07:20Z"}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f211aacf551afbf707b7fb6a40d17c8d2264110e","html_url":"https://github.com/paradigmxyz/reth/commit/f211aacf551afbf707b7fb6a40d17c8d2264110e","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f211aacf551afbf707b7fb6a40d17c8d2264110e/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"web-flow","id":19864447,"node_id":"MDQ6VXNlcjE5ODY0NDQ3","avatar_url":"https://avatars.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"0eaef1f1dcbe229b5964cf1622b3018b4a1f80b9","url":"https://api.github.com/repos/paradigmxyz/reth/commits/0eaef1f1dcbe229b5964cf1622b3018b4a1f80b9","html_url":"https://github.com/paradigmxyz/reth/commit/0eaef1f1dcbe229b5964cf1622b3018b4a1f80b9"}]},"merge_base_commit":{"sha":"7d36206dfe4348158d51d6a23b7da2e6de03841c","node_id":"C_kwDOIAWIw9oAKDdkMzYyMDZkZmU0MzQ4MTU4ZDUxZDZhMjNiN2RhMmU2ZGUwMzg0MWM","commit":{"author":{"name":"Dan Cline","email":"6798349+Rjected@users.noreply.github.com","date":"2024-02-29T15:31:11Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2024-02-29T15:31:11Z"},"message":"fix: handle both compressed and uncompressed disconnect reason decoding (#6862)","tree":{"sha":"9b246c0d93d438365481d81fbedcdd7eccdb137b","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/9b246c0d93d438365481d81fbedcdd7eccdb137b"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/7d36206dfe4348158d51d6a23b7da2e6de03841c","comment_count":1,"verification":{"verified":true,"reason":"valid","signature":"-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJl4KNOCRC1aQ7uu5UhlAAAyDUQABnP6Q2X4ML6OcDnAnDeux72\ntaAbeSobjB/rnkKiq7uDzwia/c8lRouGXjrTLNbie14uBeRS7x9VyGQ/uyeT6jE/\nU2SxJIOtXSSGQ7BkyvpIwwTGVBLHU4qmIfo+XAKqdP/RJIp659TqRIfh8+MXtf30\nQ7HPErW3zsAcEVZybIh9nVgjBrrqZPkxDdjHanc0vv6ktWaa9z3qa1sNAtUjJ8cC\nb9mjqQmGlE1VNWeZsavT8ZL5wgjIZyH0UbTVChdHrYovJtlHWviQtq9QsU9ysFZV\n+HOw1fIc0Eblr4zVJwSvVjwRZaetvLsFvyJk5yAc2WzSKh1gqjPs3E4KWh6LNovy\nH/v1KHC8P5kt7kYhj6Ic/GvmI1SkmqcpysJQ8APNQa8lxmGkkCffMv8IeuhWK4lq\n1WoKgCnSdbOLvliCbVbCYHpp3eyEMbctoBX4SywByF2w9FALDBpvs64Le2DNedi6\n2LcCseJekek/p6XjHY0qbREh9mxrWtO/IU6eys9c7PFY61mgCaYD5C4Vf6WPDdtl\nIf08Ip0Z3rMKb1c//HSB1YFhNINFbXC/us3niRWpRNBHrQv7O0Np65EGXsaGATCy\npyT3ay20RdNlUUFuBJVyq9W6teyfBNnO9cUTEm5w11ZMd2FtQpsl3QKCnW4a37Fm\nPqy0jz7wt5sL94tQw7yV\n=lqjF\n-----END PGP SIGNATURE-----\n","payload":"tree 9b246c0d93d438365481d81fbedcdd7eccdb137b\nparent 9468527aad19a083708a5ff7ac12eace67e0ce5e\nauthor Dan Cline <6798349+Rjected@users.noreply.github.com> 1709220671 -0500\ncommitter GitHub <noreply@github.com> 1709220671 +0000\n\nfix: handle both compressed and uncompressed disconnect reason decoding (#6862)\n\n","verified_at":"2024-11-07T07:02:37Z"}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/7d36206dfe4348158d51d6a23b7da2e6de03841c","html_url":"https://github.com/paradigmxyz/reth/commit/7d36206dfe4348158d51d6a23b7da2e6de03841c","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/7d36206dfe4348158d51d6a23b7da2e6de03841c/comments","author":{"login":"Rjected","id":6798349,"node_id":"MDQ6VXNlcjY3OTgzNDk=","avatar_url":"https://avatars.githubusercontent.com/u/6798349?v=4","gravatar_id":"","url":"https://api.github.com/users/Rjected","html_url":"https://github.com/Rjected","followers_url":"https://api.github.com/users/Rjected/followers","following_url":"https://api.github.com/users/Rjected/following{/other_user}","gists_url":"https://api.github.com/users/Rjected/gists{/gist_id}","starred_url":"https://api.github.com/users/Rjected/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Rjected/subscriptions","organizations_url":"https://api.github.com/users/Rjected/orgs","repos_url":"https://api.github.com/users/Rjected/repos","events_url":"https://api.github.com/users/Rjected/events{/privacy}","received_events_url":"https://api.github.com/users/Rjected/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"web-flow","id":19864447,"node_id":"MDQ6VXNlcjE5ODY0NDQ3","avatar_url":"https://avatars.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"9468527aad19a083708a5ff7ac12eace67e0ce5e","url":"https://api.github.com/repos/paradigmxyz/reth/commits/9468527aad19a083708a5ff7ac12eace67e0ce5e","html_url":"https://github.com/paradigmxyz/reth/commit/9468527aad19a083708a5ff7ac12eace67e0ce5e"}]},"status":"diverged","ahead_by":47,"behind_by":3695,"total_commits":47,"commits":[{"sha":"a789a5a2914540000907b990babc9bfaa258e839","node_id":"C_kwDOIAWIw9oAKGE3ODlhNWEyOTE0NTQwMDAwOTA3Yjk5MGJhYmM5YmZhYTI1OGU4Mzk","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:29:22Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:29:22Z"},"message":"Add crate","tree":{"sha":"caeeb4d6c96d7f927ecfdb990d8a5a1687f08bba","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/caeeb4d6c96d7f927ecfdb990d8a5a1687f08bba"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/a789a5a2914540000907b990babc9bfaa258e839","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/a789a5a2914540000907b990babc9bfaa258e839","html_url":"https://github.com/paradigmxyz/reth/commit/a789a5a2914540000907b990babc9bfaa258e839","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/a789a5a2914540000907b990babc9bfaa258e839/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"66264e25345476d52d50e70f88ab88b3694c18e9","url":"https://api.github.com/repos/paradigmxyz/reth/commits/66264e25345476d52d50e70f88ab88b3694c18e9","html_url":"https://github.com/paradigmxyz/reth/commit/66264e25345476d52d50e70f88ab88b3694c18e9"}]},{"sha":"a52ba54eab2651da1eca1b7229ecbd49e511341d","node_id":"C_kwDOIAWIw9oAKGE1MmJhNTRlYWIyNjUxZGExZWNhMWI3MjI5ZWNiZDQ5ZTUxMTM0MWQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:40:25Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:40:25Z"},"message":"add noargs","tree":{"sha":"c6351f661b7f9cc8b9b563674eba603b11098cd7","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/c6351f661b7f9cc8b9b563674eba603b11098cd7"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/a52ba54eab2651da1eca1b7229ecbd49e511341d","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/a52ba54eab2651da1eca1b7229ecbd49e511341d","html_url":"https://github.com/paradigmxyz/reth/commit/a52ba54eab2651da1eca1b7229ecbd49e511341d","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/a52ba54eab2651da1eca1b7229ecbd49e511341d/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"a789a5a2914540000907b990babc9bfaa258e839","url":"https://api.github.com/repos/paradigmxyz/reth/commits/a789a5a2914540000907b990babc9bfaa258e839","html_url":"https://github.com/paradigmxyz/reth/commit/a789a5a2914540000907b990babc9bfaa258e839"}]},{"sha":"85197e86603acfc34dd29adc41512753fc7309ae","node_id":"C_kwDOIAWIw9oAKDg1MTk3ZTg2NjAzYWNmYzM0ZGQyOWFkYzQxNTEyNzUzZmM3MzA5YWU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:48:56Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T13:48:56Z"},"message":"chore: add launch function","tree":{"sha":"f86f00809c2e2b8fa4b794bdf8a07774d99ce215","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/f86f00809c2e2b8fa4b794bdf8a07774d99ce215"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/85197e86603acfc34dd29adc41512753fc7309ae","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/85197e86603acfc34dd29adc41512753fc7309ae","html_url":"https://github.com/paradigmxyz/reth/commit/85197e86603acfc34dd29adc41512753fc7309ae","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/85197e86603acfc34dd29adc41512753fc7309ae/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"a52ba54eab2651da1eca1b7229ecbd49e511341d","url":"https://api.github.com/repos/paradigmxyz/reth/commits/a52ba54eab2651da1eca1b7229ecbd49e511341d","html_url":"https://github.com/paradigmxyz/reth/commit/a52ba54eab2651da1eca1b7229ecbd49e511341d"}]},{"sha":"5f9e70a32a5cc630bdc509cf44f87006d227a377","node_id":"C_kwDOIAWIw9oAKDVmOWU3MGEzMmE1Y2M2MzBiZGM1MDljZjQ0Zjg3MDA2ZDIyN2EzNzc","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T16:16:57Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T16:16:57Z"},"message":"chore: work on lauch","tree":{"sha":"28057e5258f628ec50be52c38b00e83f8f651246","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/28057e5258f628ec50be52c38b00e83f8f651246"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/5f9e70a32a5cc630bdc509cf44f87006d227a377","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/5f9e70a32a5cc630bdc509cf44f87006d227a377","html_url":"https://github.com/paradigmxyz/reth/commit/5f9e70a32a5cc630bdc509cf44f87006d227a377","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/5f9e70a32a5cc630bdc509cf44f87006d227a377/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"85197e86603acfc34dd29adc41512753fc7309ae","url":"https://api.github.com/repos/paradigmxyz/reth/commits/85197e86603acfc34dd29adc41512753fc7309ae","html_url":"https://github.com/paradigmxyz/reth/commit/85197e86603acfc34dd29adc41512753fc7309ae"}]},{"sha":"acd5aa0ed653138810d90206d44b74235e567c58","node_id":"C_kwDOIAWIw9oAKGFjZDVhYTBlZDY1MzEzODgxMGQ5MDIwNmQ0NGI3NDIzNWU1NjdjNTg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T16:34:11Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-14T16:34:11Z"},"message":"chore: add run ethereum","tree":{"sha":"0c681ed1a449d8aa08505d4020ce42dfb7a41455","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/0c681ed1a449d8aa08505d4020ce42dfb7a41455"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/acd5aa0ed653138810d90206d44b74235e567c58","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/acd5aa0ed653138810d90206d44b74235e567c58","html_url":"https://github.com/paradigmxyz/reth/commit/acd5aa0ed653138810d90206d44b74235e567c58","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/acd5aa0ed653138810d90206d44b74235e567c58/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"5f9e70a32a5cc630bdc509cf44f87006d227a377","url":"https://api.github.com/repos/paradigmxyz/reth/commits/5f9e70a32a5cc630bdc509cf44f87006d227a377","html_url":"https://github.com/paradigmxyz/reth/commit/5f9e70a32a5cc630bdc509cf44f87006d227a377"}]},{"sha":"0665d7487706eceadc7c4616a770d14e8e6ad5e0","node_id":"C_kwDOIAWIw9oAKDA2NjVkNzQ4NzcwNmVjZWFkYzdjNDYxNmE3NzBkMTRlOGU2YWQ1ZTA","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:00:16Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:00:16Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"c2803a4f1eac0cbaeb75961a1b3ee995d0b46091","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/c2803a4f1eac0cbaeb75961a1b3ee995d0b46091"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/0665d7487706eceadc7c4616a770d14e8e6ad5e0","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/0665d7487706eceadc7c4616a770d14e8e6ad5e0","html_url":"https://github.com/paradigmxyz/reth/commit/0665d7487706eceadc7c4616a770d14e8e6ad5e0","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/0665d7487706eceadc7c4616a770d14e8e6ad5e0/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"acd5aa0ed653138810d90206d44b74235e567c58","url":"https://api.github.com/repos/paradigmxyz/reth/commits/acd5aa0ed653138810d90206d44b74235e567c58","html_url":"https://github.com/paradigmxyz/reth/commit/acd5aa0ed653138810d90206d44b74235e567c58"},{"sha":"db158f29f46aef53d23a0906996ce23080ccc021","url":"https://api.github.com/repos/paradigmxyz/reth/commits/db158f29f46aef53d23a0906996ce23080ccc021","html_url":"https://github.com/paradigmxyz/reth/commit/db158f29f46aef53d23a0906996ce23080ccc021"}]},{"sha":"c695ae1f4ac742686ae5fe00ceed1eee5df5f537","node_id":"C_kwDOIAWIw9oAKGM2OTVhZTFmNGFjNzQyNjg2YWU1ZmUwMGNlZWQxZWVlNWRmNWY1Mzc","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:27:49Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:27:49Z"},"message":"make it compile","tree":{"sha":"060ee9e92913124a55785c0c88da7ce1b1333ef2","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/060ee9e92913124a55785c0c88da7ce1b1333ef2"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/c695ae1f4ac742686ae5fe00ceed1eee5df5f537","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/c695ae1f4ac742686ae5fe00ceed1eee5df5f537","html_url":"https://github.com/paradigmxyz/reth/commit/c695ae1f4ac742686ae5fe00ceed1eee5df5f537","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/c695ae1f4ac742686ae5fe00ceed1eee5df5f537/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"0665d7487706eceadc7c4616a770d14e8e6ad5e0","url":"https://api.github.com/repos/paradigmxyz/reth/commits/0665d7487706eceadc7c4616a770d14e8e6ad5e0","html_url":"https://github.com/paradigmxyz/reth/commit/0665d7487706eceadc7c4616a770d14e8e6ad5e0"}]},{"sha":"177708989448047d2edfe6d02c71369c913537f8","node_id":"C_kwDOIAWIw9oAKDE3NzcwODk4OTQ0ODA0N2QyZWRmZTZkMDJjNzEzNjljOTEzNTM3Zjg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:33:45Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:33:45Z"},"message":"migrate main","tree":{"sha":"636e1ef1644a98391a5f7633b5f766d0cfa0d179","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/636e1ef1644a98391a5f7633b5f766d0cfa0d179"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/177708989448047d2edfe6d02c71369c913537f8","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/177708989448047d2edfe6d02c71369c913537f8","html_url":"https://github.com/paradigmxyz/reth/commit/177708989448047d2edfe6d02c71369c913537f8","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/177708989448047d2edfe6d02c71369c913537f8/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"c695ae1f4ac742686ae5fe00ceed1eee5df5f537","url":"https://api.github.com/repos/paradigmxyz/reth/commits/c695ae1f4ac742686ae5fe00ceed1eee5df5f537","html_url":"https://github.com/paradigmxyz/reth/commit/c695ae1f4ac742686ae5fe00ceed1eee5df5f537"}]},{"sha":"3fafb614eb1323385a0c778e2ec5b112940621d8","node_id":"C_kwDOIAWIw9oAKDNmYWZiNjE0ZWIxMzIzMzg1YTBjNzc4ZTJlYzViMTEyOTQwNjIxZDg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:35:16Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T14:35:16Z"},"message":"enable evm config","tree":{"sha":"fb3b7a4a9bc68ec6e9087197952c380ef2f5f7db","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/fb3b7a4a9bc68ec6e9087197952c380ef2f5f7db"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/3fafb614eb1323385a0c778e2ec5b112940621d8","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/3fafb614eb1323385a0c778e2ec5b112940621d8","html_url":"https://github.com/paradigmxyz/reth/commit/3fafb614eb1323385a0c778e2ec5b112940621d8","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/3fafb614eb1323385a0c778e2ec5b112940621d8/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"177708989448047d2edfe6d02c71369c913537f8","url":"https://api.github.com/repos/paradigmxyz/reth/commits/177708989448047d2edfe6d02c71369c913537f8","html_url":"https://github.com/paradigmxyz/reth/commit/177708989448047d2edfe6d02c71369c913537f8"}]},{"sha":"99195c1b5edeee91dd380895e1305af33ea7f7e4","node_id":"C_kwDOIAWIw9oAKDk5MTk1YzFiNWVkZWVlOTFkZDM4MDg5NWUxMzA1YWYzM2VhN2Y3ZTQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:07:04Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:07:04Z"},"message":"migrate binaries","tree":{"sha":"71cc80fb7836702283f80f1654c1117f3a4abfed","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/71cc80fb7836702283f80f1654c1117f3a4abfed"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/99195c1b5edeee91dd380895e1305af33ea7f7e4","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/99195c1b5edeee91dd380895e1305af33ea7f7e4","html_url":"https://github.com/paradigmxyz/reth/commit/99195c1b5edeee91dd380895e1305af33ea7f7e4","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/99195c1b5edeee91dd380895e1305af33ea7f7e4/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"3fafb614eb1323385a0c778e2ec5b112940621d8","url":"https://api.github.com/repos/paradigmxyz/reth/commits/3fafb614eb1323385a0c778e2ec5b112940621d8","html_url":"https://github.com/paradigmxyz/reth/commit/3fafb614eb1323385a0c778e2ec5b112940621d8"}]},{"sha":"abecb65363528f5ea062fcb900875a6460beba36","node_id":"C_kwDOIAWIw9oAKGFiZWNiNjUzNjM1MjhmNWVhMDYyZmNiOTAwODc1YTY0NjBiZWJhMzY","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:09:50Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:09:50Z"},"message":"remove rollup args","tree":{"sha":"89de49bb9829f0f8f8ef637f0ea47791b7e20645","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/89de49bb9829f0f8f8ef637f0ea47791b7e20645"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/abecb65363528f5ea062fcb900875a6460beba36","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/abecb65363528f5ea062fcb900875a6460beba36","html_url":"https://github.com/paradigmxyz/reth/commit/abecb65363528f5ea062fcb900875a6460beba36","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/abecb65363528f5ea062fcb900875a6460beba36/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"99195c1b5edeee91dd380895e1305af33ea7f7e4","url":"https://api.github.com/repos/paradigmxyz/reth/commits/99195c1b5edeee91dd380895e1305af33ea7f7e4","html_url":"https://github.com/paradigmxyz/reth/commit/99195c1b5edeee91dd380895e1305af33ea7f7e4"}]},{"sha":"f40594442af46a1dc52ad02c7083fc5b54e44784","node_id":"C_kwDOIAWIw9oAKGY0MDU5NDQ0MmFmNDZhMWRjNTJhZDAyYzcwODNmYzViNTRlNDQ3ODQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:11:14Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:11:14Z"},"message":"fix compile error","tree":{"sha":"278f2244e81c20b24d09e4c51825d5ecde707f06","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/278f2244e81c20b24d09e4c51825d5ecde707f06"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f40594442af46a1dc52ad02c7083fc5b54e44784","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f40594442af46a1dc52ad02c7083fc5b54e44784","html_url":"https://github.com/paradigmxyz/reth/commit/f40594442af46a1dc52ad02c7083fc5b54e44784","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f40594442af46a1dc52ad02c7083fc5b54e44784/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"abecb65363528f5ea062fcb900875a6460beba36","url":"https://api.github.com/repos/paradigmxyz/reth/commits/abecb65363528f5ea062fcb900875a6460beba36","html_url":"https://github.com/paradigmxyz/reth/commit/abecb65363528f5ea062fcb900875a6460beba36"}]},{"sha":"f6e0c6b991e832495ba15cab01105128f058c454","node_id":"C_kwDOIAWIw9oAKGY2ZTBjNmI5OTFlODMyNDk1YmExNWNhYjAxMTA1MTI4ZjA1OGM0NTQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:18:40Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:18:40Z"},"message":"port engine interceptor","tree":{"sha":"b95adfe6b937e899d141825003989c68eb7fe7e5","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/b95adfe6b937e899d141825003989c68eb7fe7e5"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f6e0c6b991e832495ba15cab01105128f058c454","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f6e0c6b991e832495ba15cab01105128f058c454","html_url":"https://github.com/paradigmxyz/reth/commit/f6e0c6b991e832495ba15cab01105128f058c454","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f6e0c6b991e832495ba15cab01105128f058c454/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f40594442af46a1dc52ad02c7083fc5b54e44784","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f40594442af46a1dc52ad02c7083fc5b54e44784","html_url":"https://github.com/paradigmxyz/reth/commit/f40594442af46a1dc52ad02c7083fc5b54e44784"}]},{"sha":"743691d9605d86cc4195a8e403e17134bca8aa7f","node_id":"C_kwDOIAWIw9oAKDc0MzY5MWQ5NjA1ZDg2Y2M0MTk1YThlNDAzZTE3MTM0YmNhOGFhN2Y","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:45:54Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T15:45:54Z"},"message":"chore: use futures block on","tree":{"sha":"a6a59afce51a8425d7f0a3c9b16a68152bc2abd4","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/a6a59afce51a8425d7f0a3c9b16a68152bc2abd4"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/743691d9605d86cc4195a8e403e17134bca8aa7f","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/743691d9605d86cc4195a8e403e17134bca8aa7f","html_url":"https://github.com/paradigmxyz/reth/commit/743691d9605d86cc4195a8e403e17134bca8aa7f","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/743691d9605d86cc4195a8e403e17134bca8aa7f/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f6e0c6b991e832495ba15cab01105128f058c454","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f6e0c6b991e832495ba15cab01105128f058c454","html_url":"https://github.com/paradigmxyz/reth/commit/f6e0c6b991e832495ba15cab01105128f058c454"}]},{"sha":"7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","node_id":"C_kwDOIAWIw9oAKDdhMmMzOTIzNTFjZjczYTE5ZTRkYjNkZDJkNGEyYjg0MWQ2ZjM3NjQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:02:04Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:02:04Z"},"message":"asyincify component traits","tree":{"sha":"c5165e6773c5e1e51ea0b7dbdd6318ab1922ad8a","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/c5165e6773c5e1e51ea0b7dbdd6318ab1922ad8a"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","html_url":"https://github.com/paradigmxyz/reth/commit/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"743691d9605d86cc4195a8e403e17134bca8aa7f","url":"https://api.github.com/repos/paradigmxyz/reth/commits/743691d9605d86cc4195a8e403e17134bca8aa7f","html_url":"https://github.com/paradigmxyz/reth/commit/743691d9605d86cc4195a8e403e17134bca8aa7f"}]},{"sha":"dc8ee5e30cf8965bed5cb5f310664e93cc84582b","node_id":"C_kwDOIAWIw9oAKGRjOGVlNWUzMGNmODk2NWJlZDVjYjVmMzEwNjY0ZTkzY2M4NDU4MmI","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:11:20Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:11:20Z"},"message":"impl for async closures","tree":{"sha":"75bc5a4860a6cebf39cd74d44f3fd394c84bd978","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/75bc5a4860a6cebf39cd74d44f3fd394c84bd978"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/dc8ee5e30cf8965bed5cb5f310664e93cc84582b","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/dc8ee5e30cf8965bed5cb5f310664e93cc84582b","html_url":"https://github.com/paradigmxyz/reth/commit/dc8ee5e30cf8965bed5cb5f310664e93cc84582b","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/dc8ee5e30cf8965bed5cb5f310664e93cc84582b/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","url":"https://api.github.com/repos/paradigmxyz/reth/commits/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764","html_url":"https://github.com/paradigmxyz/reth/commit/7a2c392351cf73a19e4db3dd2d4a2b841d6f3764"}]},{"sha":"f291d852be5d0a399b16962bbe8de28a584b33ef","node_id":"C_kwDOIAWIw9oAKGYyOTFkODUyYmU1ZDBhMzk5YjE2OTYyYmJlOGRlMjhhNTg0YjMzZWY","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:33:49Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:33:49Z"},"message":"migrate example","tree":{"sha":"5604ae5789d3de7affd3be7072b6ad83f497836a","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/5604ae5789d3de7affd3be7072b6ad83f497836a"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f291d852be5d0a399b16962bbe8de28a584b33ef","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f291d852be5d0a399b16962bbe8de28a584b33ef","html_url":"https://github.com/paradigmxyz/reth/commit/f291d852be5d0a399b16962bbe8de28a584b33ef","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f291d852be5d0a399b16962bbe8de28a584b33ef/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"dc8ee5e30cf8965bed5cb5f310664e93cc84582b","url":"https://api.github.com/repos/paradigmxyz/reth/commits/dc8ee5e30cf8965bed5cb5f310664e93cc84582b","html_url":"https://github.com/paradigmxyz/reth/commit/dc8ee5e30cf8965bed5cb5f310664e93cc84582b"}]},{"sha":"f5f14e1035fc4985aa4cc263541caf2632c7c348","node_id":"C_kwDOIAWIw9oAKGY1ZjE0ZTEwMzVmYzQ5ODVhYTRjYzI2MzU0MWNhZjI2MzJjN2MzNDg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:48:55Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T16:48:55Z"},"message":"migrate more examples","tree":{"sha":"58506a4bf546e6fe5730bd301376b3ad7f5a75e4","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/58506a4bf546e6fe5730bd301376b3ad7f5a75e4"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f5f14e1035fc4985aa4cc263541caf2632c7c348","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f5f14e1035fc4985aa4cc263541caf2632c7c348","html_url":"https://github.com/paradigmxyz/reth/commit/f5f14e1035fc4985aa4cc263541caf2632c7c348","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f5f14e1035fc4985aa4cc263541caf2632c7c348/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f291d852be5d0a399b16962bbe8de28a584b33ef","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f291d852be5d0a399b16962bbe8de28a584b33ef","html_url":"https://github.com/paradigmxyz/reth/commit/f291d852be5d0a399b16962bbe8de28a584b33ef"}]},{"sha":"5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","node_id":"C_kwDOIAWIw9oAKDVkZDhhNmM0YmUyZGRmMDliNWMzMjNiZWRmYTQ5NjVhYTg4ZTI4MDk","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:19:50Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:19:50Z"},"message":"migrate more","tree":{"sha":"8c0a68dbcaa0e0986b2989c7b0a84c33d24e896d","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/8c0a68dbcaa0e0986b2989c7b0a84c33d24e896d"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","html_url":"https://github.com/paradigmxyz/reth/commit/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f5f14e1035fc4985aa4cc263541caf2632c7c348","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f5f14e1035fc4985aa4cc263541caf2632c7c348","html_url":"https://github.com/paradigmxyz/reth/commit/f5f14e1035fc4985aa4cc263541caf2632c7c348"}]},{"sha":"d083d73494a02105236681cf2a58178c9a18b9d2","node_id":"C_kwDOIAWIw9oAKGQwODNkNzM0OTRhMDIxMDUyMzY2ODFjZjJhNTgxNzhjOWExOGI5ZDI","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:36:11Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:36:11Z"},"message":"chore: migrate more","tree":{"sha":"9e85ecf6048cdb221d7807889f3d9c428cb074f3","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/9e85ecf6048cdb221d7807889f3d9c428cb074f3"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/d083d73494a02105236681cf2a58178c9a18b9d2","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/d083d73494a02105236681cf2a58178c9a18b9d2","html_url":"https://github.com/paradigmxyz/reth/commit/d083d73494a02105236681cf2a58178c9a18b9d2","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/d083d73494a02105236681cf2a58178c9a18b9d2/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","url":"https://api.github.com/repos/paradigmxyz/reth/commits/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809","html_url":"https://github.com/paradigmxyz/reth/commit/5dd8a6c4be2ddf09b5c323bedfa4965aa88e2809"}]},{"sha":"1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","node_id":"C_kwDOIAWIw9oAKDFlOGQxNmMxYThjYTM1NmI0MDA4ZGZjMWE2YzE1ZTQzZmQxMjZkMDU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:43:09Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:43:09Z"},"message":"chore: migrate example","tree":{"sha":"34dd21fa819e5457420e73830fb75711666e5573","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/34dd21fa819e5457420e73830fb75711666e5573"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","html_url":"https://github.com/paradigmxyz/reth/commit/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"d083d73494a02105236681cf2a58178c9a18b9d2","url":"https://api.github.com/repos/paradigmxyz/reth/commits/d083d73494a02105236681cf2a58178c9a18b9d2","html_url":"https://github.com/paradigmxyz/reth/commit/d083d73494a02105236681cf2a58178c9a18b9d2"}]},{"sha":"295337ed78c8d239be978aada153d41394eef8f4","node_id":"C_kwDOIAWIw9oAKDI5NTMzN2VkNzhjOGQyMzliZTk3OGFhZGExNTNkNDEzOTRlZWY4ZjQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:45:48Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T17:45:48Z"},"message":"fix clippy","tree":{"sha":"438ef15b96694950b49906b474e855ceda656724","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/438ef15b96694950b49906b474e855ceda656724"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/295337ed78c8d239be978aada153d41394eef8f4","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/295337ed78c8d239be978aada153d41394eef8f4","html_url":"https://github.com/paradigmxyz/reth/commit/295337ed78c8d239be978aada153d41394eef8f4","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/295337ed78c8d239be978aada153d41394eef8f4/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","url":"https://api.github.com/repos/paradigmxyz/reth/commits/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05","html_url":"https://github.com/paradigmxyz/reth/commit/1e8d16c1a8ca356b4008dfc1a6c15e43fd126d05"}]},{"sha":"7b51d987f13df61a0327e0199455de52adbd41a9","node_id":"C_kwDOIAWIw9oAKDdiNTFkOTg3ZjEzZGY2MWEwMzI3ZTAxOTk0NTVkZTUyYWRiZDQxYTk","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T18:07:26Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T18:07:26Z"},"message":"cleanup","tree":{"sha":"a6ef8bed583f4611d3cbb715b1051b99b6630ad8","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/a6ef8bed583f4611d3cbb715b1051b99b6630ad8"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/7b51d987f13df61a0327e0199455de52adbd41a9","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/7b51d987f13df61a0327e0199455de52adbd41a9","html_url":"https://github.com/paradigmxyz/reth/commit/7b51d987f13df61a0327e0199455de52adbd41a9","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/7b51d987f13df61a0327e0199455de52adbd41a9/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"295337ed78c8d239be978aada153d41394eef8f4","url":"https://api.github.com/repos/paradigmxyz/reth/commits/295337ed78c8d239be978aada153d41394eef8f4","html_url":"https://github.com/paradigmxyz/reth/commit/295337ed78c8d239be978aada153d41394eef8f4"}]},{"sha":"a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","node_id":"C_kwDOIAWIw9oAKGE2ZWJmNTJjZWNlNDhkNGE0ZWQ1YmZmYTY0NjRlYTczNGRkYmUyZmM","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:09:28Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:09:28Z"},"message":"more example","tree":{"sha":"6229ed2a4b5829dd2ef3efd089c49648ae04d361","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/6229ed2a4b5829dd2ef3efd089c49648ae04d361"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","html_url":"https://github.com/paradigmxyz/reth/commit/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"7b51d987f13df61a0327e0199455de52adbd41a9","url":"https://api.github.com/repos/paradigmxyz/reth/commits/7b51d987f13df61a0327e0199455de52adbd41a9","html_url":"https://github.com/paradigmxyz/reth/commit/7b51d987f13df61a0327e0199455de52adbd41a9"}]},{"sha":"f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","node_id":"C_kwDOIAWIw9oAKGY4YmQxZmMxMGRhNjhkNzkyZjVhZDZlMGI1M2UxODc2NmFjZDRiMGY","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:25:47Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:25:47Z"},"message":"fixes","tree":{"sha":"b7208829d0a89761d202e0982dd32b6e00dfd692","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/b7208829d0a89761d202e0982dd32b6e00dfd692"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","html_url":"https://github.com/paradigmxyz/reth/commit/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","url":"https://api.github.com/repos/paradigmxyz/reth/commits/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc","html_url":"https://github.com/paradigmxyz/reth/commit/a6ebf52cece48d4a4ed5bffa6464ea734ddbe2fc"}]},{"sha":"00db04b3715609f50a2b323e3e04fcd285cd6a08","node_id":"C_kwDOIAWIw9oAKDAwZGIwNGIzNzE1NjA5ZjUwYTJiMzIzZTNlMDRmY2QyODVjZDZhMDg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:29:40Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T19:29:40Z"},"message":"clippy","tree":{"sha":"659a6c6e3f74ddc923e3a159a73c6166655bbbc2","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/659a6c6e3f74ddc923e3a159a73c6166655bbbc2"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/00db04b3715609f50a2b323e3e04fcd285cd6a08","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/00db04b3715609f50a2b323e3e04fcd285cd6a08","html_url":"https://github.com/paradigmxyz/reth/commit/00db04b3715609f50a2b323e3e04fcd285cd6a08","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/00db04b3715609f50a2b323e3e04fcd285cd6a08/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f","html_url":"https://github.com/paradigmxyz/reth/commit/f8bd1fc10da68d792f5ad6e0b53e18766acd4b0f"}]},{"sha":"7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","node_id":"C_kwDOIAWIw9oAKDc2NjZjZGIyZmIwN2JjYzViMWZlYzVkYWE0NTY1NDgyYTBhZGJjYWI","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T20:03:38Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-15T20:03:38Z"},"message":"fix: use separate receipt root functions","tree":{"sha":"acd4bc3fb1f55312c8fa306bb4930e0343326bff","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/acd4bc3fb1f55312c8fa306bb4930e0343326bff"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","html_url":"https://github.com/paradigmxyz/reth/commit/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"00db04b3715609f50a2b323e3e04fcd285cd6a08","url":"https://api.github.com/repos/paradigmxyz/reth/commits/00db04b3715609f50a2b323e3e04fcd285cd6a08","html_url":"https://github.com/paradigmxyz/reth/commit/00db04b3715609f50a2b323e3e04fcd285cd6a08"}]},{"sha":"74fbb1bf0f44ca121f9f6ffaab98c8e129919510","node_id":"C_kwDOIAWIw9oAKDc0ZmJiMWJmMGY0NGNhMTIxZjlmNmZmYWFiOThjOGUxMjk5MTk1MTA","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T10:39:37Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T10:39:37Z"},"message":"add node trait","tree":{"sha":"bd4be1bcc950a3879e59f8a314550872583a6588","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/bd4be1bcc950a3879e59f8a314550872583a6588"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/74fbb1bf0f44ca121f9f6ffaab98c8e129919510","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/74fbb1bf0f44ca121f9f6ffaab98c8e129919510","html_url":"https://github.com/paradigmxyz/reth/commit/74fbb1bf0f44ca121f9f6ffaab98c8e129919510","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/74fbb1bf0f44ca121f9f6ffaab98c8e129919510/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","url":"https://api.github.com/repos/paradigmxyz/reth/commits/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab","html_url":"https://github.com/paradigmxyz/reth/commit/7666cdb2fb07bcc5b1fec5daa4565482a0adbcab"}]},{"sha":"16e5a518031dbf654c51420dbf8781e158075b89","node_id":"C_kwDOIAWIw9oAKDE2ZTVhNTE4MDMxZGJmNjU0YzUxNDIwZGJmODc4MWUxNTgwNzViODk","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T11:37:59Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T11:37:59Z"},"message":"add node trait","tree":{"sha":"bbd9b52cf089814a59d94fc2e54b56110129bed1","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/bbd9b52cf089814a59d94fc2e54b56110129bed1"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/16e5a518031dbf654c51420dbf8781e158075b89","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/16e5a518031dbf654c51420dbf8781e158075b89","html_url":"https://github.com/paradigmxyz/reth/commit/16e5a518031dbf654c51420dbf8781e158075b89","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/16e5a518031dbf654c51420dbf8781e158075b89/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"74fbb1bf0f44ca121f9f6ffaab98c8e129919510","url":"https://api.github.com/repos/paradigmxyz/reth/commits/74fbb1bf0f44ca121f9f6ffaab98c8e129919510","html_url":"https://github.com/paradigmxyz/reth/commit/74fbb1bf0f44ca121f9f6ffaab98c8e129919510"}]},{"sha":"aced888b0c282d3680b449fa54ada26befe2c91e","node_id":"C_kwDOIAWIw9oAKGFjZWQ4ODhiMGMyODJkMzY4MGI0NDlmYTU0YWRhMjZiZWZlMmM5MWU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T11:45:17Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T11:45:17Z"},"message":"chore: docs","tree":{"sha":"67f1d9ff1df324fddb832bea71c8e1d7705554ca","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/67f1d9ff1df324fddb832bea71c8e1d7705554ca"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/aced888b0c282d3680b449fa54ada26befe2c91e","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/aced888b0c282d3680b449fa54ada26befe2c91e","html_url":"https://github.com/paradigmxyz/reth/commit/aced888b0c282d3680b449fa54ada26befe2c91e","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/aced888b0c282d3680b449fa54ada26befe2c91e/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"16e5a518031dbf654c51420dbf8781e158075b89","url":"https://api.github.com/repos/paradigmxyz/reth/commits/16e5a518031dbf654c51420dbf8781e158075b89","html_url":"https://github.com/paradigmxyz/reth/commit/16e5a518031dbf654c51420dbf8781e158075b89"}]},{"sha":"e4990128968927e4f693a0cdba79f7b53609a34a","node_id":"C_kwDOIAWIw9oAKGU0OTkwMTI4OTY4OTI3ZTRmNjkzYTBjZGJhNzlmN2I1MzYwOWEzNGE","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T12:18:34Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T12:18:34Z"},"message":"more docs","tree":{"sha":"b43931ba3588c9987ca471888d9e920a5c81ced1","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/b43931ba3588c9987ca471888d9e920a5c81ced1"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/e4990128968927e4f693a0cdba79f7b53609a34a","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/e4990128968927e4f693a0cdba79f7b53609a34a","html_url":"https://github.com/paradigmxyz/reth/commit/e4990128968927e4f693a0cdba79f7b53609a34a","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/e4990128968927e4f693a0cdba79f7b53609a34a/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"aced888b0c282d3680b449fa54ada26befe2c91e","url":"https://api.github.com/repos/paradigmxyz/reth/commits/aced888b0c282d3680b449fa54ada26befe2c91e","html_url":"https://github.com/paradigmxyz/reth/commit/aced888b0c282d3680b449fa54ada26befe2c91e"}]},{"sha":"9d0aaa15318e514c1aafdd52d793cde37c843a64","node_id":"C_kwDOIAWIw9oAKDlkMGFhYTE1MzE4ZTUxNGMxYWFmZGQ1MmQ3OTNjZGUzN2M4NDNhNjQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T12:54:03Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T12:54:03Z"},"message":"update node example","tree":{"sha":"aa39e208b7afddc4423596a1ba3a5a5cadd7e23f","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/aa39e208b7afddc4423596a1ba3a5a5cadd7e23f"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/9d0aaa15318e514c1aafdd52d793cde37c843a64","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/9d0aaa15318e514c1aafdd52d793cde37c843a64","html_url":"https://github.com/paradigmxyz/reth/commit/9d0aaa15318e514c1aafdd52d793cde37c843a64","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/9d0aaa15318e514c1aafdd52d793cde37c843a64/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"e4990128968927e4f693a0cdba79f7b53609a34a","url":"https://api.github.com/repos/paradigmxyz/reth/commits/e4990128968927e4f693a0cdba79f7b53609a34a","html_url":"https://github.com/paradigmxyz/reth/commit/e4990128968927e4f693a0cdba79f7b53609a34a"}]},{"sha":"f1a26b1c8724f241164ddef573c36fd318141184","node_id":"C_kwDOIAWIw9oAKGYxYTI2YjFjODcyNGYyNDExNjRkZGVmNTczYzM2ZmQzMTgxNDExODQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:02:29Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:02:29Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"dbdadf8a6a2e6bfe8fe78dc80ee3b3fa43334552","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/dbdadf8a6a2e6bfe8fe78dc80ee3b3fa43334552"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f1a26b1c8724f241164ddef573c36fd318141184","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f1a26b1c8724f241164ddef573c36fd318141184","html_url":"https://github.com/paradigmxyz/reth/commit/f1a26b1c8724f241164ddef573c36fd318141184","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f1a26b1c8724f241164ddef573c36fd318141184/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"9d0aaa15318e514c1aafdd52d793cde37c843a64","url":"https://api.github.com/repos/paradigmxyz/reth/commits/9d0aaa15318e514c1aafdd52d793cde37c843a64","html_url":"https://github.com/paradigmxyz/reth/commit/9d0aaa15318e514c1aafdd52d793cde37c843a64"},{"sha":"683b252f83d1ab4f1d47a7f24e3e76fd0463f84f","url":"https://api.github.com/repos/paradigmxyz/reth/commits/683b252f83d1ab4f1d47a7f24e3e76fd0463f84f","html_url":"https://github.com/paradigmxyz/reth/commit/683b252f83d1ab4f1d47a7f24e3e76fd0463f84f"}]},{"sha":"5854d83581d61432dbd657e493565dfc9a75652b","node_id":"C_kwDOIAWIw9oAKDU4NTRkODM1ODFkNjE0MzJkYmQ2NTdlNDkzNTY1ZGZjOWE3NTY1MmI","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:08:27Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:08:27Z"},"message":"rename","tree":{"sha":"aecf27b28f8a3a2195e3f7d1a569a5d3b267dbf3","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/aecf27b28f8a3a2195e3f7d1a569a5d3b267dbf3"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/5854d83581d61432dbd657e493565dfc9a75652b","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/5854d83581d61432dbd657e493565dfc9a75652b","html_url":"https://github.com/paradigmxyz/reth/commit/5854d83581d61432dbd657e493565dfc9a75652b","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/5854d83581d61432dbd657e493565dfc9a75652b/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f1a26b1c8724f241164ddef573c36fd318141184","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f1a26b1c8724f241164ddef573c36fd318141184","html_url":"https://github.com/paradigmxyz/reth/commit/f1a26b1c8724f241164ddef573c36fd318141184"}]},{"sha":"162fc6db33b184b069c8cbe30e5ed0e203ee1555","node_id":"C_kwDOIAWIw9oAKDE2MmZjNmRiMzNiMTg0YjA2OWM4Y2JlMzBlNWVkMGUyMDNlZTE1NTU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:14:32Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-16T18:14:32Z"},"message":"fix missing fn","tree":{"sha":"3f7dcb98fbbbec4dafe2c0665b03a3c99cf1e8ac","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/3f7dcb98fbbbec4dafe2c0665b03a3c99cf1e8ac"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/162fc6db33b184b069c8cbe30e5ed0e203ee1555","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/162fc6db33b184b069c8cbe30e5ed0e203ee1555","html_url":"https://github.com/paradigmxyz/reth/commit/162fc6db33b184b069c8cbe30e5ed0e203ee1555","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/162fc6db33b184b069c8cbe30e5ed0e203ee1555/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"5854d83581d61432dbd657e493565dfc9a75652b","url":"https://api.github.com/repos/paradigmxyz/reth/commits/5854d83581d61432dbd657e493565dfc9a75652b","html_url":"https://github.com/paradigmxyz/reth/commit/5854d83581d61432dbd657e493565dfc9a75652b"}]},{"sha":"97feba2f872cc1f238b0eb161504cc1aaed4d4a8","node_id":"C_kwDOIAWIw9oAKDk3ZmViYTJmODcyY2MxZjIzOGIwZWIxNjE1MDRjYzFhYWVkNGQ0YTg","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T08:48:23Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T08:48:23Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"7abc1a7b0b21e3967a637143f9324bfa4179d7b7","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/7abc1a7b0b21e3967a637143f9324bfa4179d7b7"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/97feba2f872cc1f238b0eb161504cc1aaed4d4a8","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/97feba2f872cc1f238b0eb161504cc1aaed4d4a8","html_url":"https://github.com/paradigmxyz/reth/commit/97feba2f872cc1f238b0eb161504cc1aaed4d4a8","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/97feba2f872cc1f238b0eb161504cc1aaed4d4a8/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"162fc6db33b184b069c8cbe30e5ed0e203ee1555","url":"https://api.github.com/repos/paradigmxyz/reth/commits/162fc6db33b184b069c8cbe30e5ed0e203ee1555","html_url":"https://github.com/paradigmxyz/reth/commit/162fc6db33b184b069c8cbe30e5ed0e203ee1555"},{"sha":"a5dc8d66799412d3e19f6c80e4857ffac0269a5a","url":"https://api.github.com/repos/paradigmxyz/reth/commits/a5dc8d66799412d3e19f6c80e4857ffac0269a5a","html_url":"https://github.com/paradigmxyz/reth/commit/a5dc8d66799412d3e19f6c80e4857ffac0269a5a"}]},{"sha":"6254ddbb1eca48c2f962535c2f6ee669934bdc5e","node_id":"C_kwDOIAWIw9oAKDYyNTRkZGJiMWVjYTQ4YzJmOTYyNTM1YzJmNmVlNjY5OTM0YmRjNWU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T08:59:12Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T08:59:12Z"},"message":"cleanup","tree":{"sha":"626a32f388008f8cfac49c168f3f067313eb4bd3","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/626a32f388008f8cfac49c168f3f067313eb4bd3"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/6254ddbb1eca48c2f962535c2f6ee669934bdc5e","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/6254ddbb1eca48c2f962535c2f6ee669934bdc5e","html_url":"https://github.com/paradigmxyz/reth/commit/6254ddbb1eca48c2f962535c2f6ee669934bdc5e","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/6254ddbb1eca48c2f962535c2f6ee669934bdc5e/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"97feba2f872cc1f238b0eb161504cc1aaed4d4a8","url":"https://api.github.com/repos/paradigmxyz/reth/commits/97feba2f872cc1f238b0eb161504cc1aaed4d4a8","html_url":"https://github.com/paradigmxyz/reth/commit/97feba2f872cc1f238b0eb161504cc1aaed4d4a8"}]},{"sha":"cd494ba06227c551062467935852ee9f759d8dcb","node_id":"C_kwDOIAWIw9oAKGNkNDk0YmEwNjIyN2M1NTEwNjI0Njc5MzU4NTJlZTlmNzU5ZDhkY2I","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T09:05:00Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-20T09:05:49Z"},"message":"fixes","tree":{"sha":"4e0426c0419030dfd11f8ee7619025df813ab5db","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/4e0426c0419030dfd11f8ee7619025df813ab5db"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/cd494ba06227c551062467935852ee9f759d8dcb","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/cd494ba06227c551062467935852ee9f759d8dcb","html_url":"https://github.com/paradigmxyz/reth/commit/cd494ba06227c551062467935852ee9f759d8dcb","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/cd494ba06227c551062467935852ee9f759d8dcb/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"6254ddbb1eca48c2f962535c2f6ee669934bdc5e","url":"https://api.github.com/repos/paradigmxyz/reth/commits/6254ddbb1eca48c2f962535c2f6ee669934bdc5e","html_url":"https://github.com/paradigmxyz/reth/commit/6254ddbb1eca48c2f962535c2f6ee669934bdc5e"}]},{"sha":"e952573bf686ab5dd07f2f4352e504a5d4615994","node_id":"C_kwDOIAWIw9oAKGU5NTI1NzNiZjY4NmFiNWRkMDdmMmY0MzUyZTUwNGE1ZDQ2MTU5OTQ","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T10:49:23Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T10:49:23Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"038cc6d0a495066c1d07fab91826f81e96502cfd","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/038cc6d0a495066c1d07fab91826f81e96502cfd"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/e952573bf686ab5dd07f2f4352e504a5d4615994","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/e952573bf686ab5dd07f2f4352e504a5d4615994","html_url":"https://github.com/paradigmxyz/reth/commit/e952573bf686ab5dd07f2f4352e504a5d4615994","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/e952573bf686ab5dd07f2f4352e504a5d4615994/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"cd494ba06227c551062467935852ee9f759d8dcb","url":"https://api.github.com/repos/paradigmxyz/reth/commits/cd494ba06227c551062467935852ee9f759d8dcb","html_url":"https://github.com/paradigmxyz/reth/commit/cd494ba06227c551062467935852ee9f759d8dcb"},{"sha":"a27626cc224498e1b7524e248ee836858006b831","url":"https://api.github.com/repos/paradigmxyz/reth/commits/a27626cc224498e1b7524e248ee836858006b831","html_url":"https://github.com/paradigmxyz/reth/commit/a27626cc224498e1b7524e248ee836858006b831"}]},{"sha":"136622e9bc182d0b82fc265aa202fda214eeb68c","node_id":"C_kwDOIAWIw9oAKDEzNjYyMmU5YmMxODJkMGI4MmZjMjY1YWEyMDJmZGEyMTRlZWI2OGM","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T10:53:53Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T10:53:53Z"},"message":"add evm example","tree":{"sha":"96eea43fc91304dac68ec3687d777ce478db0aee","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/96eea43fc91304dac68ec3687d777ce478db0aee"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/136622e9bc182d0b82fc265aa202fda214eeb68c","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/136622e9bc182d0b82fc265aa202fda214eeb68c","html_url":"https://github.com/paradigmxyz/reth/commit/136622e9bc182d0b82fc265aa202fda214eeb68c","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/136622e9bc182d0b82fc265aa202fda214eeb68c/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"e952573bf686ab5dd07f2f4352e504a5d4615994","url":"https://api.github.com/repos/paradigmxyz/reth/commits/e952573bf686ab5dd07f2f4352e504a5d4615994","html_url":"https://github.com/paradigmxyz/reth/commit/e952573bf686ab5dd07f2f4352e504a5d4615994"}]},{"sha":"c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","node_id":"C_kwDOIAWIw9oAKGM4ZTkxNWVkNmY3OTE4NzE3Y2JjYTU0YWU1ZDBlNTc1NWUyYzRlMjc","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T11:33:14Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-27T11:33:14Z"},"message":"feat: add custom precompile example","tree":{"sha":"4408905b471c6c7a375182d770ad975b04092f7e","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/4408905b471c6c7a375182d770ad975b04092f7e"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","html_url":"https://github.com/paradigmxyz/reth/commit/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"136622e9bc182d0b82fc265aa202fda214eeb68c","url":"https://api.github.com/repos/paradigmxyz/reth/commits/136622e9bc182d0b82fc265aa202fda214eeb68c","html_url":"https://github.com/paradigmxyz/reth/commit/136622e9bc182d0b82fc265aa202fda214eeb68c"}]},{"sha":"cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","node_id":"C_kwDOIAWIw9oAKGNiYzNhM2VmZGFlOGFiM2MxZTEzZWI3ZWIzNWQ5ZWFhMDZkYzA2MjA","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:11:04Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:11:04Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"41cfda1dc7b5073f26bee23a436d8d4a114a668a","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/41cfda1dc7b5073f26bee23a436d8d4a114a668a"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","html_url":"https://github.com/paradigmxyz/reth/commit/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","url":"https://api.github.com/repos/paradigmxyz/reth/commits/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27","html_url":"https://github.com/paradigmxyz/reth/commit/c8e915ed6f7918717cbca54ae5d0e5755e2c4e27"},{"sha":"19ff1fb35c3d6031e368f5588269af6d66223d3a","url":"https://api.github.com/repos/paradigmxyz/reth/commits/19ff1fb35c3d6031e368f5588269af6d66223d3a","html_url":"https://github.com/paradigmxyz/reth/commit/19ff1fb35c3d6031e368f5588269af6d66223d3a"}]},{"sha":"f85b24efebf0a2da361d6ff75470bf69cee81af1","node_id":"C_kwDOIAWIw9oAKGY4NWIyNGVmZWJmMGEyZGEzNjFkNmZmNzU0NzBiZjY5Y2VlODFhZjE","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:25:34Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:25:34Z"},"message":"resolve conflicts","tree":{"sha":"0882765847173d848d5268978732d3c8cc3aca98","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/0882765847173d848d5268978732d3c8cc3aca98"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/f85b24efebf0a2da361d6ff75470bf69cee81af1","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/f85b24efebf0a2da361d6ff75470bf69cee81af1","html_url":"https://github.com/paradigmxyz/reth/commit/f85b24efebf0a2da361d6ff75470bf69cee81af1","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/f85b24efebf0a2da361d6ff75470bf69cee81af1/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","url":"https://api.github.com/repos/paradigmxyz/reth/commits/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620","html_url":"https://github.com/paradigmxyz/reth/commit/cbc3a3efdae8ab3c1e13eb7eb35d9eaa06dc0620"}]},{"sha":"56d74edb3296e2995a71a1c3585d226f095a0d95","node_id":"C_kwDOIAWIw9oAKDU2ZDc0ZWRiMzI5NmUyOTk1YTcxYTFjMzU4NWQyMjZmMDk1YTBkOTU","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:31:17Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:31:17Z"},"message":"migrate example","tree":{"sha":"11e71978f718ea23f68029f434baeaa11c6b9338","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/11e71978f718ea23f68029f434baeaa11c6b9338"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/56d74edb3296e2995a71a1c3585d226f095a0d95","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/56d74edb3296e2995a71a1c3585d226f095a0d95","html_url":"https://github.com/paradigmxyz/reth/commit/56d74edb3296e2995a71a1c3585d226f095a0d95","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/56d74edb3296e2995a71a1c3585d226f095a0d95/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"f85b24efebf0a2da361d6ff75470bf69cee81af1","url":"https://api.github.com/repos/paradigmxyz/reth/commits/f85b24efebf0a2da361d6ff75470bf69cee81af1","html_url":"https://github.com/paradigmxyz/reth/commit/f85b24efebf0a2da361d6ff75470bf69cee81af1"}]},{"sha":"34b3ea818d647e8685dbe3af53d722fda642ec51","node_id":"C_kwDOIAWIw9oAKDM0YjNlYTgxOGQ2NDdlODY4NWRiZTNhZjUzZDcyMmZkYTY0MmVjNTE","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:41:10Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T15:41:10Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"d77452b4c5d78728158de30fc92cf590e7588ef8","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/d77452b4c5d78728158de30fc92cf590e7588ef8"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/34b3ea818d647e8685dbe3af53d722fda642ec51","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/34b3ea818d647e8685dbe3af53d722fda642ec51","html_url":"https://github.com/paradigmxyz/reth/commit/34b3ea818d647e8685dbe3af53d722fda642ec51","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/34b3ea818d647e8685dbe3af53d722fda642ec51/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"56d74edb3296e2995a71a1c3585d226f095a0d95","url":"https://api.github.com/repos/paradigmxyz/reth/commits/56d74edb3296e2995a71a1c3585d226f095a0d95","html_url":"https://github.com/paradigmxyz/reth/commit/56d74edb3296e2995a71a1c3585d226f095a0d95"},{"sha":"9468527aad19a083708a5ff7ac12eace67e0ce5e","url":"https://api.github.com/repos/paradigmxyz/reth/commits/9468527aad19a083708a5ff7ac12eace67e0ce5e","html_url":"https://github.com/paradigmxyz/reth/commit/9468527aad19a083708a5ff7ac12eace67e0ce5e"}]},{"sha":"d253fa70e73928e06a1e1f88b1175aab25065d37","node_id":"C_kwDOIAWIw9oAKGQyNTNmYTcwZTczOTI4ZTA2YTFlMWY4OGIxMTc1YWFiMjUwNjVkMzc","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T16:26:55Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T16:26:55Z"},"message":"Merge branch 'main' into matt/integrate-node-builder","tree":{"sha":"d473aaf412545b2930979c7e83fd2650cbbb7502","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/d473aaf412545b2930979c7e83fd2650cbbb7502"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/d253fa70e73928e06a1e1f88b1175aab25065d37","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/d253fa70e73928e06a1e1f88b1175aab25065d37","html_url":"https://github.com/paradigmxyz/reth/commit/d253fa70e73928e06a1e1f88b1175aab25065d37","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/d253fa70e73928e06a1e1f88b1175aab25065d37/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"34b3ea818d647e8685dbe3af53d722fda642ec51","url":"https://api.github.com/repos/paradigmxyz/reth/commits/34b3ea818d647e8685dbe3af53d722fda642ec51","html_url":"https://github.com/paradigmxyz/reth/commit/34b3ea818d647e8685dbe3af53d722fda642ec51"},{"sha":"7d36206dfe4348158d51d6a23b7da2e6de03841c","url":"https://api.github.com/repos/paradigmxyz/reth/commits/7d36206dfe4348158d51d6a23b7da2e6de03841c","html_url":"https://github.com/paradigmxyz/reth/commit/7d36206dfe4348158d51d6a23b7da2e6de03841c"}]},{"sha":"43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","node_id":"C_kwDOIAWIw9oAKDQzYzJjNmMzNmFmNzA0ZThhN2Q3YmZhNGM1NTFlOTZkMzQ2YjFhNmE","commit":{"author":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T21:16:15Z"},"committer":{"name":"Matthias Seitz","email":"matthias.seitz@outlook.de","date":"2024-02-29T21:16:15Z"},"message":"perf: rm redundant collect","tree":{"sha":"e7ebf6222dce9f4ba65b41b19c572fbba151dde6","url":"https://api.github.com/repos/paradigmxyz/reth/git/trees/e7ebf6222dce9f4ba65b41b19c572fbba151dde6"},"url":"https://api.github.com/repos/paradigmxyz/reth/git/commits/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null,"verified_at":null}},"url":"https://api.github.com/repos/paradigmxyz/reth/commits/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","html_url":"https://github.com/paradigmxyz/reth/commit/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","comments_url":"https://api.github.com/repos/paradigmxyz/reth/commits/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/comments","author":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"mattsse","id":19890894,"node_id":"MDQ6VXNlcjE5ODkwODk0","avatar_url":"https://avatars.githubusercontent.com/u/19890894?v=4","gravatar_id":"","url":"https://api.github.com/users/mattsse","html_url":"https://github.com/mattsse","followers_url":"https://api.github.com/users/mattsse/followers","following_url":"https://api.github.com/users/mattsse/following{/other_user}","gists_url":"https://api.github.com/users/mattsse/gists{/gist_id}","starred_url":"https://api.github.com/users/mattsse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattsse/subscriptions","organizations_url":"https://api.github.com/users/mattsse/orgs","repos_url":"https://api.github.com/users/mattsse/repos","events_url":"https://api.github.com/users/mattsse/events{/privacy}","received_events_url":"https://api.github.com/users/mattsse/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"d253fa70e73928e06a1e1f88b1175aab25065d37","url":"https://api.github.com/repos/paradigmxyz/reth/commits/d253fa70e73928e06a1e1f88b1175aab25065d37","html_url":"https://github.com/paradigmxyz/reth/commit/d253fa70e73928e06a1e1f88b1175aab25065d37"}]}],"files":[{"sha":"20a05ceab9b27a058e3be00a4700cd9be214ded2","filename":"Cargo.lock","status":"modified","additions":54,"deletions":19,"changes":73,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/Cargo.lock","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/Cargo.lock","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/Cargo.lock?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -20,6 +20,7 @@ dependencies = [\n  \"eyre\",\n  \"jsonrpsee\",\n  \"reth\",\n+ \"reth-node-ethereum\",\n  \"reth-transaction-pool\",\n  \"tokio\",\n ]\n@@ -798,12 +799,10 @@ name = \"beacon-api-sse\"\n version = \"0.0.0\"\n dependencies = [\n  \"clap\",\n- \"eyre\",\n  \"futures-util\",\n  \"mev-share-sse\",\n  \"reth\",\n- \"serde\",\n- \"serde_json\",\n+ \"reth-node-ethereum\",\n  \"tokio\",\n  \"tracing\",\n ]\n@@ -1391,9 +1390,8 @@ checksum = \"98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce\"\n name = \"cli-extension-event-hooks\"\n version = \"0.0.0\"\n dependencies = [\n- \"clap\",\n- \"eyre\",\n  \"reth\",\n+ \"reth-node-ethereum\",\n ]\n \n [[package]]\n@@ -1816,14 +1814,43 @@ dependencies = [\n  \"syn 2.0.50\",\n ]\n \n+[[package]]\n+name = \"custom-dev-node\"\n+version = \"0.0.0\"\n+dependencies = [\n+ \"eyre\",\n+ \"futures-util\",\n+ \"reth\",\n+ \"reth-node-core\",\n+ \"reth-node-ethereum\",\n+ \"reth-primitives\",\n+ \"serde_json\",\n+ \"tokio\",\n+]\n+\n+[[package]]\n+name = \"custom-evm\"\n+version = \"0.0.0\"\n+dependencies = [\n+ \"alloy-chains\",\n+ \"eyre\",\n+ \"reth\",\n+ \"reth-node-api\",\n+ \"reth-node-core\",\n+ \"reth-node-ethereum\",\n+ \"reth-primitives\",\n+ \"reth-tracing\",\n+ \"tokio\",\n+]\n+\n [[package]]\n name = \"custom-inspector\"\n version = \"0.0.0\"\n dependencies = [\n  \"clap\",\n- \"eyre\",\n  \"futures-util\",\n  \"reth\",\n+ \"reth-node-ethereum\",\n ]\n \n [[package]]\n@@ -1832,32 +1859,45 @@ version = \"0.0.0\"\n dependencies = [\n  \"alloy-chains\",\n  \"eyre\",\n- \"jsonrpsee\",\n  \"reth\",\n+ \"reth-basic-payload-builder\",\n+ \"reth-ethereum-payload-builder\",\n  \"reth-node-api\",\n  \"reth-node-core\",\n+ \"reth-node-ethereum\",\n  \"reth-payload-builder\",\n  \"reth-primitives\",\n- \"reth-rpc-api\",\n  \"reth-rpc-types\",\n+ \"reth-tracing\",\n  \"serde\",\n  \"thiserror\",\n  \"tokio\",\n ]\n \n+[[package]]\n+name = \"custom-node-components\"\n+version = \"0.0.0\"\n+dependencies = [\n+ \"eyre\",\n+ \"reth\",\n+ \"reth-node-ethereum\",\n+ \"reth-tracing\",\n+ \"reth-transaction-pool\",\n+]\n+\n [[package]]\n name = \"custom-payload-builder\"\n version = \"0.0.0\"\n dependencies = [\n- \"clap\",\n  \"eyre\",\n  \"futures-util\",\n  \"reth\",\n  \"reth-basic-payload-builder\",\n+ \"reth-ethereum-payload-builder\",\n  \"reth-node-api\",\n+ \"reth-node-ethereum\",\n  \"reth-payload-builder\",\n  \"reth-primitives\",\n- \"tokio\",\n  \"tracing\",\n ]\n \n@@ -5739,6 +5779,7 @@ dependencies = [\n  \"reth-network-api\",\n  \"reth-nippy-jar\",\n  \"reth-node-api\",\n+ \"reth-node-builder\",\n  \"reth-node-core\",\n  \"reth-node-ethereum\",\n  \"reth-node-optimism\",\n@@ -5774,11 +5815,7 @@ dependencies = [\n name = \"reth-auto-seal-consensus\"\n version = \"0.1.0-alpha.21\"\n dependencies = [\n- \"clap\",\n- \"eyre\",\n  \"futures-util\",\n- \"jsonrpsee\",\n- \"reth\",\n  \"reth-beacon-consensus\",\n  \"reth-interfaces\",\n  \"reth-node-api\",\n@@ -5787,8 +5824,6 @@ dependencies = [\n  \"reth-revm\",\n  \"reth-stages\",\n  \"reth-transaction-pool\",\n- \"serde_json\",\n- \"tempfile\",\n  \"tokio\",\n  \"tokio-stream\",\n  \"tracing\",\n@@ -6472,6 +6507,7 @@ dependencies = [\n name = \"reth-node-ethereum\"\n version = \"0.1.0-alpha.21\"\n dependencies = [\n+ \"async-trait\",\n  \"eyre\",\n  \"reth-basic-payload-builder\",\n  \"reth-db\",\n@@ -6493,6 +6529,7 @@ dependencies = [\n name = \"reth-node-optimism\"\n version = \"0.1.0-alpha.21\"\n dependencies = [\n+ \"clap\",\n  \"eyre\",\n  \"reth-basic-payload-builder\",\n  \"reth-db\",\n@@ -8600,11 +8637,9 @@ name = \"trace-transaction-cli\"\n version = \"0.0.0\"\n dependencies = [\n  \"clap\",\n- \"eyre\",\n  \"futures-util\",\n- \"jsonrpsee\",\n  \"reth\",\n- \"tokio\",\n+ \"reth-node-ethereum\",\n ]\n \n [[package]]"},{"sha":"83988cff72ffcea4f061f46cb77e19159e22843e","filename":"Cargo.toml","status":"modified","additions":3,"deletions":0,"changes":3,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/Cargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/Cargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/Cargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -60,7 +60,10 @@ members = [\n     \"examples/additional-rpc-namespace-in-cli/\",\n     \"examples/beacon-api-sse/\",\n     \"examples/cli-extension-event-hooks/\",\n+    \"examples/custom-evm/\",\n     \"examples/custom-node/\",\n+    \"examples/custom-node-components/\",\n+    \"examples/custom-dev-node/\",\n     \"examples/custom-payload-builder/\",\n     \"examples/manual-p2p/\",\n     \"examples/rpc-db/\","},{"sha":"1a4abe5a9daa8822322db9c18c797b75f5f8bec1","filename":"bin/reth/Cargo.toml","status":"modified","additions":1,"deletions":2,"changes":3,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -53,6 +53,7 @@ reth-node-optimism = { workspace = true, optional = true, features = [\n     \"optimism\",\n ] }\n reth-node-core.workspace = true\n+reth-node-builder.workspace = true\n \n # crypto\n alloy-rlp.workspace = true\n@@ -137,8 +138,6 @@ optimism = [\n     \"reth-blockchain-tree/optimism\",\n     \"reth-payload-builder/optimism\",\n     \"reth-optimism-payload-builder/optimism\",\n-    \"reth-ethereum-payload-builder/optimism\",\n-    \"reth-node-ethereum/optimism\",\n     \"dep:reth-node-optimism\",\n     \"reth-node-core/optimism\",\n ]"},{"sha":"d6f18c5039bbd78507bef1c1a6984c9d779e1796","filename":"bin/reth/src/builder.rs","status":"removed","additions":0,"deletions":849,"changes":849,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/bin%2Freth%2Fsrc%2Fbuilder.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/bin%2Freth%2Fsrc%2Fbuilder.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fbuilder.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,849 +0,0 @@\n-//! Contains types and methods that can be used to launch a node based off of a [NodeConfig].\n-\n-use crate::commands::debug_cmd::engine_api_store::EngineApiStore;\n-use eyre::Context;\n-use fdlimit::raise_fd_limit;\n-use futures::{future::Either, stream, stream_select, StreamExt};\n-use reth_auto_seal_consensus::AutoSealBuilder;\n-use reth_beacon_consensus::{\n-    hooks::{EngineHooks, PruneHook, StaticFileHook},\n-    BeaconConsensusEngine, MIN_BLOCKS_FOR_PIPELINE_RUN,\n-};\n-use reth_blockchain_tree::{config::BlockchainTreeConfig, ShareableBlockchainTree};\n-use reth_config::Config;\n-use reth_db::{\n-    database::Database,\n-    database_metrics::{DatabaseMetadata, DatabaseMetrics},\n-};\n-use reth_interfaces::p2p::either::EitherDownloader;\n-use reth_network::NetworkEvents;\n-use reth_network_api::{NetworkInfo, PeersInfo};\n-use reth_node_core::{\n-    cli::{\n-        components::{RethNodeComponentsImpl, RethRpcServerHandles},\n-        config::RethRpcConfig,\n-        db_type::DatabaseInstance,\n-        ext::{DefaultRethNodeCommandConfig, RethCliExt, RethNodeCommandConfig},\n-    },\n-    dirs::{ChainPath, DataDirPath},\n-    events::cl::ConsensusLayerHealthEvents,\n-    exit::NodeExitFuture,\n-    init::init_genesis,\n-    version::SHORT_VERSION,\n-};\n-#[cfg(not(feature = \"optimism\"))]\n-use reth_node_ethereum::{EthEngineTypes, EthEvmConfig};\n-#[cfg(feature = \"optimism\")]\n-use reth_node_optimism::{OptimismEngineTypes, OptimismEvmConfig};\n-use reth_payload_builder::PayloadBuilderHandle;\n-use reth_primitives::format_ether;\n-use reth_provider::{providers::BlockchainProvider, ProviderFactory};\n-use reth_prune::PrunerBuilder;\n-use reth_rpc_engine_api::EngineApi;\n-use reth_static_file::StaticFileProducer;\n-use reth_tasks::{TaskExecutor, TaskManager};\n-use reth_transaction_pool::TransactionPool;\n-use std::{path::PathBuf, sync::Arc};\n-use tokio::sync::{mpsc::unbounded_channel, oneshot};\n-use tracing::*;\n-\n-/// Re-export `NodeConfig` from `reth_node_core`.\n-pub use reth_node_core::node_config::NodeConfig;\n-\n-/// Launches the node, also adding any RPC extensions passed.\n-///\n-/// # Example\n-/// ```rust\n-/// # use reth_tasks::{TaskManager, TaskSpawner};\n-/// # use reth_node_core::node_config::NodeConfig;\n-/// # use reth_node_core::cli::{\n-/// #     ext::DefaultRethNodeCommandConfig,\n-/// # };\n-/// # use tokio::runtime::Handle;\n-/// # use reth::builder::launch_from_config;\n-///\n-/// async fn t() {\n-///     let handle = Handle::current();\n-///     let manager = TaskManager::new(handle);\n-///     let executor = manager.executor();\n-///     let builder = NodeConfig::default();\n-///     let ext = DefaultRethNodeCommandConfig::default();\n-///     let handle = launch_from_config::<()>(builder, ext, executor).await.unwrap();\n-/// }\n-/// ```\n-pub async fn launch_from_config<E: RethCliExt>(\n-    mut config: NodeConfig,\n-    ext: E::Node,\n-    executor: TaskExecutor,\n-) -> eyre::Result<NodeHandle> {\n-    info!(target: \"reth::cli\", \"reth {} starting\", SHORT_VERSION);\n-\n-    // Register the prometheus recorder before creating the database,\n-    // because database init needs it to register metrics.\n-    config.install_prometheus_recorder()?;\n-\n-    let database = std::mem::take(&mut config.database);\n-    let db_instance = database.init_db(config.db.log_level, config.chain.chain)?;\n-    info!(target: \"reth::cli\", \"Database opened\");\n-\n-    match db_instance {\n-        DatabaseInstance::Real { db, data_dir } => {\n-            let builder = NodeBuilderWithDatabase { config, db, data_dir };\n-            builder.launch::<E>(ext, executor).await\n-        }\n-        DatabaseInstance::Test { db, data_dir } => {\n-            let builder = NodeBuilderWithDatabase { config, db, data_dir };\n-            builder.launch::<E>(ext, executor).await\n-        }\n-    }\n-}\n-\n-/// A version of the [NodeConfig] that has an installed database. This is used to construct the\n-/// [NodeHandle].\n-///\n-/// This also contains a path to a data dir that cannot be changed.\n-#[derive(Debug)]\n-pub struct NodeBuilderWithDatabase<DB> {\n-    /// The node config\n-    pub config: NodeConfig,\n-    /// The database\n-    pub db: Arc<DB>,\n-    /// The data dir\n-    pub data_dir: ChainPath<DataDirPath>,\n-}\n-\n-impl<DB: Database + DatabaseMetrics + DatabaseMetadata + 'static> NodeBuilderWithDatabase<DB> {\n-    /// Launch the node with the given extensions and executor\n-    pub async fn launch<E: RethCliExt>(\n-        mut self,\n-        mut ext: E::Node,\n-        executor: TaskExecutor,\n-    ) -> eyre::Result<NodeHandle> {\n-        // Raise the fd limit of the process.\n-        // Does not do anything on windows.\n-        raise_fd_limit()?;\n-\n-        // get config\n-        let config = self.load_config()?;\n-\n-        let prometheus_handle = self.config.install_prometheus_recorder()?;\n-\n-        let provider_factory = ProviderFactory::new(\n-            Arc::clone(&self.db),\n-            Arc::clone(&self.config.chain),\n-            self.data_dir.static_files_path(),\n-        )?\n-        .with_static_files_metrics();\n-\n-        self.config.start_metrics_endpoint(prometheus_handle, Arc::clone(&self.db)).await?;\n-\n-        debug!(target: \"reth::cli\", chain=%self.config.chain.chain, genesis=?self.config.chain.genesis_hash(), \"Initializing genesis\");\n-\n-        let genesis_hash = init_genesis(provider_factory.clone())?;\n-\n-        info!(target: \"reth::cli\", \"{}\", self.config.chain.display_hardforks());\n-\n-        let consensus = self.config.consensus();\n-\n-        debug!(target: \"reth::cli\", \"Spawning stages metrics listener task\");\n-        let (sync_metrics_tx, sync_metrics_rx) = unbounded_channel();\n-        let sync_metrics_listener = reth_stages::MetricsListener::new(sync_metrics_rx);\n-        executor.spawn_critical(\"stages metrics listener task\", sync_metrics_listener);\n-\n-        let prune_config = self\n-            .config\n-            .pruning\n-            .prune_config(Arc::clone(&self.config.chain))?\n-            .or(config.prune.clone());\n-\n-        // TODO: stateful node builder should be able to remove cfgs here\n-        #[cfg(feature = \"optimism\")]\n-        let evm_config = OptimismEvmConfig::default();\n-\n-        // The default payload builder is implemented on the unit type.\n-        #[cfg(not(feature = \"optimism\"))]\n-        let evm_config = EthEvmConfig::default();\n-\n-        // configure blockchain tree\n-        let tree_config = BlockchainTreeConfig::default();\n-        let tree = self.config.build_blockchain_tree(\n-            provider_factory.clone(),\n-            consensus.clone(),\n-            prune_config.clone(),\n-            sync_metrics_tx.clone(),\n-            tree_config,\n-            evm_config,\n-        )?;\n-        let canon_state_notification_sender = tree.canon_state_notification_sender();\n-        let blockchain_tree = ShareableBlockchainTree::new(tree);\n-        debug!(target: \"reth::cli\", \"configured blockchain tree\");\n-\n-        // fetch the head block from the database\n-        let head = self\n-            .config\n-            .lookup_head(provider_factory.clone())\n-            .wrap_err(\"the head block is missing\")?;\n-\n-        // setup the blockchain provider\n-        let blockchain_db =\n-            BlockchainProvider::new(provider_factory.clone(), blockchain_tree.clone())?;\n-\n-        // build transaction pool\n-        let transaction_pool =\n-            self.config.build_and_spawn_txpool(&blockchain_db, head, &executor, &self.data_dir)?;\n-\n-        // build network\n-        let mut network_builder = self\n-            .config\n-            .build_network(\n-                &config,\n-                provider_factory.clone(),\n-                executor.clone(),\n-                head,\n-                &self.data_dir,\n-            )\n-            .await?;\n-\n-        let components = RethNodeComponentsImpl::new(\n-            blockchain_db.clone(),\n-            transaction_pool.clone(),\n-            network_builder.handle(),\n-            executor.clone(),\n-            blockchain_db.clone(),\n-            evm_config,\n-        );\n-\n-        // allow network modifications\n-        ext.configure_network(network_builder.network_mut(), &components)?;\n-\n-        // launch network\n-        let network = self.config.start_network(\n-            network_builder,\n-            &executor,\n-            transaction_pool.clone(),\n-            provider_factory.clone(),\n-            &self.data_dir,\n-        );\n-\n-        info!(target: \"reth::cli\", peer_id = %network.peer_id(), local_addr = %network.local_addr(), enode = %network.local_node_record(), \"Connected to P2P network\");\n-        debug!(target: \"reth::cli\", peer_id = ?network.peer_id(), \"Full peer ID\");\n-        let network_client = network.fetch_client().await?;\n-\n-        ext.on_components_initialized(&components)?;\n-\n-        debug!(target: \"reth::cli\", \"Spawning payload builder service\");\n-\n-        // TODO: stateful node builder should handle this in with_payload_builder\n-        // Optimism's payload builder is implemented on the OptimismPayloadBuilder type.\n-        #[cfg(feature = \"optimism\")]\n-        let payload_builder = reth_optimism_payload_builder::OptimismPayloadBuilder::default()\n-            .set_compute_pending_block(self.config.builder.compute_pending_block);\n-\n-        #[cfg(feature = \"optimism\")]\n-        let payload_builder: PayloadBuilderHandle<OptimismEngineTypes> =\n-            ext.spawn_payload_builder_service(&self.config.builder, &components, payload_builder)?;\n-\n-        // The default payload builder is implemented on the unit type.\n-        #[cfg(not(feature = \"optimism\"))]\n-        let payload_builder = reth_ethereum_payload_builder::EthereumPayloadBuilder::default();\n-\n-        #[cfg(not(feature = \"optimism\"))]\n-        let payload_builder: PayloadBuilderHandle<EthEngineTypes> =\n-            ext.spawn_payload_builder_service(&self.config.builder, &components, payload_builder)?;\n-\n-        let (consensus_engine_tx, mut consensus_engine_rx) = unbounded_channel();\n-        if let Some(store_path) = self.config.debug.engine_api_store.clone() {\n-            let (engine_intercept_tx, engine_intercept_rx) = unbounded_channel();\n-            let engine_api_store = EngineApiStore::new(store_path);\n-            executor.spawn_critical(\n-                \"engine api interceptor\",\n-                engine_api_store.intercept(consensus_engine_rx, engine_intercept_tx),\n-            );\n-            consensus_engine_rx = engine_intercept_rx;\n-        };\n-        let max_block = self.config.max_block(&network_client, provider_factory.clone()).await?;\n-\n-        let mut hooks = EngineHooks::new();\n-\n-        let mut static_file_producer = StaticFileProducer::new(\n-            provider_factory.clone(),\n-            provider_factory.static_file_provider(),\n-            prune_config.clone().unwrap_or_default().segments,\n-        );\n-        let static_file_producer_events = static_file_producer.events();\n-        hooks.add(StaticFileHook::new(static_file_producer.clone(), Box::new(executor.clone())));\n-        info!(target: \"reth::cli\", \"StaticFileProducer initialized\");\n-\n-        // Configure the pipeline\n-        let (mut pipeline, client) = if self.config.dev.dev {\n-            info!(target: \"reth::cli\", \"Starting Reth in dev mode\");\n-            for (idx, (address, alloc)) in self.config.chain.genesis.alloc.iter().enumerate() {\n-                info!(target: \"reth::cli\", \"Allocated Genesis Account: {:02}. {} ({} ETH)\", idx, address.to_string(), format_ether(alloc.balance));\n-            }\n-            let mining_mode =\n-                self.config.mining_mode(transaction_pool.pending_transactions_listener());\n-\n-            let (_, client, mut task) = AutoSealBuilder::new(\n-                Arc::clone(&self.config.chain),\n-                blockchain_db.clone(),\n-                transaction_pool.clone(),\n-                consensus_engine_tx.clone(),\n-                canon_state_notification_sender,\n-                mining_mode,\n-                evm_config,\n-            )\n-            .build();\n-\n-            let mut pipeline = self\n-                .config\n-                .build_networked_pipeline(\n-                    &config.stages,\n-                    client.clone(),\n-                    Arc::clone(&consensus),\n-                    provider_factory.clone(),\n-                    &executor,\n-                    sync_metrics_tx,\n-                    prune_config.clone(),\n-                    max_block,\n-                    static_file_producer,\n-                    evm_config,\n-                )\n-                .await?;\n-\n-            let pipeline_events = pipeline.events();\n-            task.set_pipeline_events(pipeline_events);\n-            debug!(target: \"reth::cli\", \"Spawning auto mine task\");\n-            executor.spawn(Box::pin(task));\n-\n-            (pipeline, EitherDownloader::Left(client))\n-        } else {\n-            let pipeline = self\n-                .config\n-                .build_networked_pipeline(\n-                    &config.stages,\n-                    network_client.clone(),\n-                    Arc::clone(&consensus),\n-                    provider_factory.clone(),\n-                    &executor.clone(),\n-                    sync_metrics_tx,\n-                    prune_config.clone(),\n-                    max_block,\n-                    static_file_producer,\n-                    evm_config,\n-                )\n-                .await?;\n-\n-            (pipeline, EitherDownloader::Right(network_client))\n-        };\n-\n-        let pipeline_events = pipeline.events();\n-\n-        let initial_target = self.config.initial_pipeline_target(genesis_hash);\n-\n-        let prune_config = prune_config.unwrap_or_default();\n-        let mut pruner = PrunerBuilder::new(prune_config.clone())\n-            .max_reorg_depth(tree_config.max_reorg_depth() as usize)\n-            .prune_delete_limit(self.config.chain.prune_delete_limit)\n-            .build(provider_factory.clone());\n-\n-        let pruner_events = pruner.events();\n-        hooks.add(PruneHook::new(pruner, Box::new(executor.clone())));\n-        info!(target: \"reth::cli\", ?prune_config, \"Pruner initialized\");\n-\n-        // Configure the consensus engine\n-        let (beacon_consensus_engine, beacon_engine_handle) = BeaconConsensusEngine::with_channel(\n-            client,\n-            pipeline,\n-            blockchain_db.clone(),\n-            Box::new(executor.clone()),\n-            Box::new(network.clone()),\n-            max_block,\n-            self.config.debug.continuous,\n-            payload_builder.clone(),\n-            initial_target,\n-            MIN_BLOCKS_FOR_PIPELINE_RUN,\n-            consensus_engine_tx,\n-            consensus_engine_rx,\n-            hooks,\n-        )?;\n-        info!(target: \"reth::cli\", \"Consensus engine initialized\");\n-\n-        let events = stream_select!(\n-            network.event_listener().map(Into::into),\n-            beacon_engine_handle.event_listener().map(Into::into),\n-            pipeline_events.map(Into::into),\n-            if self.config.debug.tip.is_none() && !self.config.dev.dev {\n-                Either::Left(\n-                    ConsensusLayerHealthEvents::new(Box::new(blockchain_db.clone()))\n-                        .map(Into::into),\n-                )\n-            } else {\n-                Either::Right(stream::empty())\n-            },\n-            pruner_events.map(Into::into),\n-            static_file_producer_events.map(Into::into),\n-        );\n-        executor.spawn_critical(\n-            \"events task\",\n-            reth_node_core::events::node::handle_events(\n-                Some(network.clone()),\n-                Some(head.number),\n-                events,\n-                self.db.clone(),\n-            ),\n-        );\n-\n-        let engine_api = EngineApi::new(\n-            blockchain_db.clone(),\n-            self.config.chain.clone(),\n-            beacon_engine_handle,\n-            payload_builder.into(),\n-            Box::new(executor.clone()),\n-        );\n-        info!(target: \"reth::cli\", \"Engine API handler initialized\");\n-\n-        // extract the jwt secret from the args if possible\n-        let default_jwt_path = self.data_dir.jwt_path();\n-        let jwt_secret = self.config.rpc.auth_jwt_secret(default_jwt_path)?;\n-\n-        // adjust rpc port numbers based on instance number\n-        self.config.adjust_instance_ports();\n-\n-        // Start RPC servers\n-        let rpc_server_handles =\n-            self.config.rpc.start_servers(&components, engine_api, jwt_secret, &mut ext).await?;\n-\n-        // Run consensus engine to completion\n-        let (tx, rx) = oneshot::channel();\n-        info!(target: \"reth::cli\", \"Starting consensus engine\");\n-        executor.spawn_critical_blocking(\"consensus engine\", async move {\n-            let res = beacon_consensus_engine.await;\n-            let _ = tx.send(res);\n-        });\n-\n-        ext.on_node_started(&components)?;\n-\n-        // If `enable_genesis_walkback` is set to true, the rollup client will need to\n-        // perform the derivation pipeline from genesis, validating the data dir.\n-        // When set to false, set the finalized, safe, and unsafe head block hashes\n-        // on the rollup client using a fork choice update. This prevents the rollup\n-        // client from performing the derivation pipeline from genesis, and instead\n-        // starts syncing from the current tip in the DB.\n-        #[cfg(feature = \"optimism\")]\n-        if self.config.chain.is_optimism() && !self.config.rollup.enable_genesis_walkback {\n-            let client = rpc_server_handles.auth.http_client();\n-            reth_rpc_api::EngineApiClient::<OptimismEngineTypes>::fork_choice_updated_v2(\n-                &client,\n-                reth_rpc_types::engine::ForkchoiceState {\n-                    head_block_hash: head.hash,\n-                    safe_block_hash: head.hash,\n-                    finalized_block_hash: head.hash,\n-                },\n-                None,\n-            )\n-            .await?;\n-        }\n-\n-        // construct node handle and return\n-        let node_handle = NodeHandle {\n-            rpc_server_handles,\n-            node_exit_future: NodeExitFuture::new(rx, self.config.debug.terminate),\n-        };\n-        Ok(node_handle)\n-    }\n-\n-    /// Returns the path to the config file.\n-    fn config_path(&self) -> PathBuf {\n-        self.config.config.clone().unwrap_or_else(|| self.data_dir.config_path())\n-    }\n-\n-    /// Loads the reth config with the given datadir root\n-    fn load_config(&self) -> eyre::Result<Config> {\n-        let config_path = self.config_path();\n-\n-        let mut config = confy::load_path::<Config>(&config_path)\n-            .wrap_err_with(|| format!(\"Could not load config file {:?}\", config_path))?;\n-\n-        info!(target: \"reth::cli\", path = ?config_path, \"Configuration loaded\");\n-\n-        // Update the config with the command line arguments\n-        config.peers.connect_trusted_nodes_only = self.config.network.trusted_only;\n-\n-        if !self.config.network.trusted_peers.is_empty() {\n-            info!(target: \"reth::cli\", \"Adding trusted nodes\");\n-            self.config.network.trusted_peers.iter().for_each(|peer| {\n-                config.peers.trusted_nodes.insert(*peer);\n-            });\n-        }\n-\n-        Ok(config)\n-    }\n-}\n-\n-/// The [NodeHandle] contains the [RethRpcServerHandles] returned by the reth initialization\n-/// process, as well as a method for waiting for the node exit.\n-#[derive(Debug)]\n-pub struct NodeHandle {\n-    /// The handles to the RPC servers\n-    rpc_server_handles: RethRpcServerHandles,\n-\n-    /// A Future which waits node exit\n-    /// See [`NodeExitFuture`]\n-    node_exit_future: NodeExitFuture,\n-}\n-\n-impl NodeHandle {\n-    /// Returns the [RethRpcServerHandles] for this node.\n-    pub fn rpc_server_handles(&self) -> &RethRpcServerHandles {\n-        &self.rpc_server_handles\n-    }\n-\n-    /// Waits for the node to exit, if it was configured to exit.\n-    pub async fn wait_for_node_exit(self) -> eyre::Result<()> {\n-        self.node_exit_future.await\n-    }\n-}\n-\n-/// A simple function to launch a node with the specified [NodeConfig], spawning tasks on the\n-/// [TaskExecutor] constructed from [TaskManager::current].\n-///\n-/// # Example\n-/// ```\n-/// # use reth_node_core::{\n-/// #     node_config::NodeConfig,\n-/// #     args::RpcServerArgs,\n-/// # };\n-/// # use reth::builder::spawn_node;\n-/// async fn t() {\n-///     // Create a node builder with an http rpc server enabled\n-///     let rpc_args = RpcServerArgs::default().with_http();\n-///\n-///     let builder = NodeConfig::test().with_rpc(rpc_args);\n-///\n-///     // Spawn the builder, returning a handle to the node\n-///     let (_handle, _manager) = spawn_node(builder).await.unwrap();\n-/// }\n-/// ```\n-pub async fn spawn_node(config: NodeConfig) -> eyre::Result<(NodeHandle, TaskManager)> {\n-    let task_manager = TaskManager::current();\n-    let ext = DefaultRethNodeCommandConfig::default();\n-    Ok((launch_from_config::<()>(config, ext, task_manager.executor()).await?, task_manager))\n-}\n-\n-#[cfg(test)]\n-mod tests {\n-    use super::*;\n-    use reth_node_core::args::RpcServerArgs;\n-    use reth_primitives::U256;\n-    use reth_rpc_api::EthApiClient;\n-\n-    #[tokio::test]\n-    async fn block_number_node_config_test() {\n-        // this launches a test node with http\n-        let rpc_args = RpcServerArgs::default().with_http();\n-\n-        let (handle, _manager) = spawn_node(NodeConfig::test().with_rpc(rpc_args)).await.unwrap();\n-\n-        // call a function on the node\n-        let client = handle.rpc_server_handles().rpc.http_client().unwrap();\n-        let block_number = client.block_number().await.unwrap();\n-\n-        // it should be zero, since this is an ephemeral test node\n-        assert_eq!(block_number, U256::ZERO);\n-    }\n-\n-    #[tokio::test]\n-    async fn rpc_handles_none_without_http() {\n-        // this launches a test node _without_ http\n-        let (handle, _manager) = spawn_node(NodeConfig::test()).await.unwrap();\n-\n-        // ensure that the `http_client` is none\n-        let maybe_client = handle.rpc_server_handles().rpc.http_client();\n-        assert!(maybe_client.is_none());\n-    }\n-\n-    #[tokio::test]\n-    async fn launch_multiple_nodes() {\n-        // spawn_test_node takes roughly 1 second per node, so this test takes ~4 seconds\n-        let num_nodes = 4;\n-\n-        // contains handles and managers\n-        let mut handles = Vec::new();\n-        for _ in 0..num_nodes {\n-            let handle = spawn_node(NodeConfig::test()).await.unwrap();\n-            handles.push(handle);\n-        }\n-    }\n-\n-    #[cfg(feature = \"optimism\")]\n-    #[tokio::test]\n-    async fn optimism_pre_canyon_no_withdrawals_valid() {\n-        reth_tracing::init_test_tracing();\n-        use alloy_chains::Chain;\n-        use jsonrpsee::http_client::HttpClient;\n-        use reth_primitives::{ChainSpec, Genesis};\n-        use reth_rpc_api::EngineApiClient;\n-        use reth_rpc_types::engine::{\n-            ForkchoiceState, OptimismPayloadAttributes, PayloadAttributes,\n-        };\n-\n-        // this launches a test node with http\n-        let rpc_args = RpcServerArgs::default().with_http();\n-\n-        // create optimism genesis with canyon at block 2\n-        let spec = ChainSpec::builder()\n-            .chain(Chain::optimism_mainnet())\n-            .genesis(Genesis::default())\n-            .regolith_activated()\n-            .build();\n-\n-        let genesis_hash = spec.genesis_hash();\n-\n-        // create node config\n-        let node_config = NodeConfig::test().with_rpc(rpc_args).with_chain(spec);\n-\n-        let (handle, _manager) = spawn_node(node_config).await.unwrap();\n-\n-        // call a function on the node\n-        let client = handle.rpc_server_handles().auth.http_client();\n-        let block_number = client.block_number().await.unwrap();\n-\n-        // it should be zero, since this is an ephemeral test node\n-        assert_eq!(block_number, U256::ZERO);\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let forkchoice_state = ForkchoiceState {\n-            head_block_hash: genesis_hash,\n-            safe_block_hash: genesis_hash,\n-            finalized_block_hash: genesis_hash,\n-        };\n-\n-        let payload_attributes = OptimismPayloadAttributes {\n-            payload_attributes: PayloadAttributes {\n-                timestamp: 1,\n-                prev_randao: Default::default(),\n-                suggested_fee_recipient: Default::default(),\n-                // canyon is _not_ in the chain spec, so this should cause the engine call to fail\n-                withdrawals: None,\n-                parent_beacon_block_root: None,\n-            },\n-            no_tx_pool: None,\n-            gas_limit: Some(1),\n-            transactions: None,\n-        };\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let res = <HttpClient as EngineApiClient<OptimismEngineTypes>>::fork_choice_updated_v2(\n-            &client,\n-            forkchoice_state,\n-            Some(payload_attributes),\n-        )\n-        .await;\n-        res.expect(\"pre-canyon engine call without withdrawals should succeed\");\n-    }\n-\n-    #[cfg(feature = \"optimism\")]\n-    #[tokio::test]\n-    async fn optimism_pre_canyon_withdrawals_invalid() {\n-        reth_tracing::init_test_tracing();\n-        use alloy_chains::Chain;\n-        use assert_matches::assert_matches;\n-        use jsonrpsee::{core::Error, http_client::HttpClient, types::error::INVALID_PARAMS_CODE};\n-        use reth_primitives::{ChainSpec, Genesis};\n-        use reth_rpc_api::EngineApiClient;\n-        use reth_rpc_types::engine::{\n-            ForkchoiceState, OptimismPayloadAttributes, PayloadAttributes,\n-        };\n-\n-        // this launches a test node with http\n-        let rpc_args = RpcServerArgs::default().with_http();\n-\n-        // create optimism genesis with canyon at block 2\n-        let spec = ChainSpec::builder()\n-            .chain(Chain::optimism_mainnet())\n-            .genesis(Genesis::default())\n-            .regolith_activated()\n-            .build();\n-\n-        let genesis_hash = spec.genesis_hash();\n-\n-        // create node config\n-        let node_config = NodeConfig::test().with_rpc(rpc_args).with_chain(spec);\n-\n-        let (handle, _manager) = spawn_node(node_config).await.unwrap();\n-\n-        // call a function on the node\n-        let client = handle.rpc_server_handles().auth.http_client();\n-        let block_number = client.block_number().await.unwrap();\n-\n-        // it should be zero, since this is an ephemeral test node\n-        assert_eq!(block_number, U256::ZERO);\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let forkchoice_state = ForkchoiceState {\n-            head_block_hash: genesis_hash,\n-            safe_block_hash: genesis_hash,\n-            finalized_block_hash: genesis_hash,\n-        };\n-\n-        let payload_attributes = OptimismPayloadAttributes {\n-            payload_attributes: PayloadAttributes {\n-                timestamp: 1,\n-                prev_randao: Default::default(),\n-                suggested_fee_recipient: Default::default(),\n-                // canyon is _not_ in the chain spec, so this should cause the engine call to fail\n-                withdrawals: Some(vec![]),\n-                parent_beacon_block_root: None,\n-            },\n-            no_tx_pool: None,\n-            gas_limit: Some(1),\n-            transactions: None,\n-        };\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let res = <HttpClient as EngineApiClient<OptimismEngineTypes>>::fork_choice_updated_v2(\n-            &client,\n-            forkchoice_state,\n-            Some(payload_attributes),\n-        )\n-        .await;\n-        let err = res.expect_err(\"pre-canyon engine call with withdrawals should fail\");\n-        assert_matches!(err, Error::Call(ref object) if object.code() == INVALID_PARAMS_CODE);\n-    }\n-\n-    #[cfg(feature = \"optimism\")]\n-    #[tokio::test]\n-    async fn optimism_post_canyon_no_withdrawals_invalid() {\n-        reth_tracing::init_test_tracing();\n-        use alloy_chains::Chain;\n-        use assert_matches::assert_matches;\n-        use jsonrpsee::{core::Error, http_client::HttpClient, types::error::INVALID_PARAMS_CODE};\n-        use reth_primitives::{ChainSpec, Genesis};\n-        use reth_rpc_api::EngineApiClient;\n-        use reth_rpc_types::engine::{\n-            ForkchoiceState, OptimismPayloadAttributes, PayloadAttributes,\n-        };\n-\n-        // this launches a test node with http\n-        let rpc_args = RpcServerArgs::default().with_http();\n-\n-        // create optimism genesis with canyon at block 2\n-        let spec = ChainSpec::builder()\n-            .chain(Chain::optimism_mainnet())\n-            .genesis(Genesis::default())\n-            .canyon_activated()\n-            .build();\n-\n-        let genesis_hash = spec.genesis_hash();\n-\n-        // create node config\n-        let node_config = NodeConfig::test().with_rpc(rpc_args).with_chain(spec);\n-\n-        let (handle, _manager) = spawn_node(node_config).await.unwrap();\n-\n-        // call a function on the node\n-        let client = handle.rpc_server_handles().auth.http_client();\n-        let block_number = client.block_number().await.unwrap();\n-\n-        // it should be zero, since this is an ephemeral test node\n-        assert_eq!(block_number, U256::ZERO);\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let forkchoice_state = ForkchoiceState {\n-            head_block_hash: genesis_hash,\n-            safe_block_hash: genesis_hash,\n-            finalized_block_hash: genesis_hash,\n-        };\n-\n-        let payload_attributes = OptimismPayloadAttributes {\n-            payload_attributes: PayloadAttributes {\n-                timestamp: 1,\n-                prev_randao: Default::default(),\n-                suggested_fee_recipient: Default::default(),\n-                // canyon is _not_ in the chain spec, so this should cause the engine call to fail\n-                withdrawals: None,\n-                parent_beacon_block_root: None,\n-            },\n-            no_tx_pool: None,\n-            gas_limit: Some(1),\n-            transactions: None,\n-        };\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let res = <HttpClient as EngineApiClient<OptimismEngineTypes>>::fork_choice_updated_v2(\n-            &client,\n-            forkchoice_state,\n-            Some(payload_attributes),\n-        )\n-        .await;\n-        let err = res.expect_err(\"post-canyon engine call with no withdrawals should fail\");\n-        assert_matches!(err, Error::Call(ref object) if object.code() == INVALID_PARAMS_CODE);\n-    }\n-\n-    #[cfg(feature = \"optimism\")]\n-    #[tokio::test]\n-    async fn optimism_post_canyon_withdrawals_valid() {\n-        reth_tracing::init_test_tracing();\n-        use alloy_chains::Chain;\n-        use jsonrpsee::http_client::HttpClient;\n-        use reth_primitives::{ChainSpec, Genesis};\n-        use reth_rpc_api::EngineApiClient;\n-        use reth_rpc_types::engine::{\n-            ForkchoiceState, OptimismPayloadAttributes, PayloadAttributes,\n-        };\n-\n-        // this launches a test node with http\n-        let rpc_args = RpcServerArgs::default().with_http();\n-\n-        // create optimism genesis with canyon at block 2\n-        let spec = ChainSpec::builder()\n-            .chain(Chain::optimism_mainnet())\n-            .genesis(Genesis::default())\n-            .canyon_activated()\n-            .build();\n-\n-        let genesis_hash = spec.genesis_hash();\n-\n-        // create node config\n-        let node_config = NodeConfig::test().with_rpc(rpc_args).with_chain(spec);\n-\n-        let (handle, _manager) = spawn_node(node_config).await.unwrap();\n-\n-        // call a function on the node\n-        let client = handle.rpc_server_handles().auth.http_client();\n-        let block_number = client.block_number().await.unwrap();\n-\n-        // it should be zero, since this is an ephemeral test node\n-        assert_eq!(block_number, U256::ZERO);\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let forkchoice_state = ForkchoiceState {\n-            head_block_hash: genesis_hash,\n-            safe_block_hash: genesis_hash,\n-            finalized_block_hash: genesis_hash,\n-        };\n-\n-        let payload_attributes = OptimismPayloadAttributes {\n-            payload_attributes: PayloadAttributes {\n-                timestamp: 1,\n-                prev_randao: Default::default(),\n-                suggested_fee_recipient: Default::default(),\n-                // canyon is _not_ in the chain spec, so this should cause the engine call to fail\n-                withdrawals: Some(vec![]),\n-                parent_beacon_block_root: None,\n-            },\n-            no_tx_pool: None,\n-            gas_limit: Some(1),\n-            transactions: None,\n-        };\n-\n-        // call the engine_forkchoiceUpdated function with payload attributes\n-        let res = <HttpClient as EngineApiClient<OptimismEngineTypes>>::fork_choice_updated_v2(\n-            &client,\n-            forkchoice_state,\n-            Some(payload_attributes),\n-        )\n-        .await;\n-        res.expect(\"post-canyon engine call with withdrawals should succeed\");\n-    }\n-}"},{"sha":"abe6345fea8615627dfbdbf08f45f36be799d677","filename":"bin/reth/src/cli/mod.rs","status":"modified","additions":80,"deletions":51,"changes":131,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcli%2Fmod.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcli%2Fmod.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fcli%2Fmod.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,18 +5,19 @@ use crate::{\n         utils::{chain_help, genesis_value_parser, SUPPORTED_CHAINS},\n         LogArgs,\n     },\n-    cli::ext::RethCliExt,\n     commands::{\n-        config_cmd, db, debug_cmd, dump_genesis, import, init_cmd, node, p2p, recover, stage,\n-        test_vectors,\n+        config_cmd, db, debug_cmd, dump_genesis, import, init_cmd, node, node::NoArgs, p2p,\n+        recover, stage, test_vectors,\n     },\n     core::cli::runner::CliRunner,\n     version::{LONG_VERSION, SHORT_VERSION},\n };\n use clap::{value_parser, Parser, Subcommand};\n+use reth_db::DatabaseEnv;\n+use reth_node_builder::{InitState, WithLaunchContext};\n use reth_primitives::ChainSpec;\n use reth_tracing::FileWorkerGuard;\n-use std::sync::Arc;\n+use std::{ffi::OsString, fmt, future::Future, sync::Arc};\n \n /// Re-export of the `reth_node_core` types specifically in the `cli` module.\n ///\n@@ -30,7 +31,7 @@ pub use crate::core::cli::*;\n /// This is the entrypoint to the executable.\n #[derive(Debug, Parser)]\n #[command(author, version = SHORT_VERSION, long_version = LONG_VERSION, about = \"Reth\", long_about = None)]\n-pub struct Cli<Ext: RethCliExt = ()> {\n+pub struct Cli<Ext: clap::Args + fmt::Debug = NoArgs> {\n     /// The command to run\n     #[command(subcommand)]\n     command: Commands<Ext>,\n@@ -68,9 +69,70 @@ pub struct Cli<Ext: RethCliExt = ()> {\n     logs: LogArgs,\n }\n \n-impl<Ext: RethCliExt> Cli<Ext> {\n+impl Cli {\n+    /// Parsers only the default CLI arguments\n+    pub fn parse_args() -> Self {\n+        Self::parse()\n+    }\n+\n+    /// Parsers only the default CLI arguments from the given iterator\n+    pub fn try_parse_args_from<I, T>(itr: I) -> Result<Self, clap::error::Error>\n+    where\n+        I: IntoIterator<Item = T>,\n+        T: Into<OsString> + Clone,\n+    {\n+        Cli::try_parse_from(itr)\n+    }\n+}\n+\n+impl<Ext: clap::Args + fmt::Debug> Cli<Ext> {\n     /// Execute the configured cli command.\n-    pub fn run(mut self) -> eyre::Result<()> {\n+    ///\n+    /// This accepts a closure that is used to launch the node via the\n+    /// [NodeCommand](node::NodeCommand).\n+    ///\n+    ///\n+    /// # Example\n+    ///\n+    /// ```no_run\n+    /// use reth::cli::Cli;\n+    /// use reth_node_ethereum::EthereumNode;\n+    ///\n+    /// Cli::parse_args()\n+    ///     .run(|builder, _| async move {\n+    ///         let handle = builder.launch_node(EthereumNode::default()).await?;\n+    ///\n+    ///         handle.wait_for_node_exit().await\n+    ///     })\n+    ///     .unwrap();\n+    /// ```\n+    ///\n+    /// # Example\n+    ///\n+    /// Parse additional CLI arguments for the node command and use it to configure the node.\n+    ///\n+    /// ```no_run\n+    /// use clap::Parser;\n+    /// use reth::cli::Cli;\n+    ///\n+    /// #[derive(Debug, Parser)]\n+    /// pub struct MyArgs {\n+    ///     pub enable: bool,\n+    /// }\n+    ///\n+    /// Cli::parse()\n+    ///     .run(|builder, my_args: MyArgs| async move {\n+    ///         // launch the node\n+    ///\n+    ///         Ok(())\n+    ///     })\n+    ///     .unwrap();\n+    /// ````\n+    pub fn run<L, Fut>(mut self, launcher: L) -> eyre::Result<()>\n+    where\n+        L: FnOnce(WithLaunchContext<Arc<DatabaseEnv>, InitState>, Ext) -> Fut,\n+        Fut: Future<Output = eyre::Result<()>>,\n+    {\n         // add network name to logs dir\n         self.logs.log_file_directory =\n             self.logs.log_file_directory.join(self.chain.chain.to_string());\n@@ -79,7 +141,9 @@ impl<Ext: RethCliExt> Cli<Ext> {\n \n         let runner = CliRunner::default();\n         match self.command {\n-            Commands::Node(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)),\n+            Commands::Node(command) => {\n+                runner.run_command_until_exit(|ctx| command.execute(ctx, launcher))\n+            }\n             Commands::Init(command) => runner.run_blocking_until_ctrl_c(command.execute()),\n             Commands::Import(command) => runner.run_blocking_until_ctrl_c(command.execute()),\n             Commands::DumpGenesis(command) => runner.run_blocking_until_ctrl_c(command.execute()),\n@@ -101,26 +165,11 @@ impl<Ext: RethCliExt> Cli<Ext> {\n         let guard = self.logs.init_tracing()?;\n         Ok(guard)\n     }\n-\n-    /// Configures the given node extension.\n-    pub fn with_node_extension<C>(mut self, conf: C) -> Self\n-    where\n-        C: Into<Ext::Node>,\n-    {\n-        self.command.set_node_extension(conf.into());\n-        self\n-    }\n-}\n-\n-/// Convenience function for parsing CLI options, set up logging and run the chosen command.\n-#[inline]\n-pub fn run() -> eyre::Result<()> {\n-    Cli::<()>::parse().run()\n }\n \n /// Commands to be executed\n #[derive(Debug, Subcommand)]\n-pub enum Commands<Ext: RethCliExt = ()> {\n+pub enum Commands<Ext: clap::Args + fmt::Debug = NoArgs> {\n     /// Start the node\n     #[command(name = \"node\")]\n     Node(node::NodeCommand<Ext>),\n@@ -155,17 +204,6 @@ pub enum Commands<Ext: RethCliExt = ()> {\n     Recover(recover::Command),\n }\n \n-impl<Ext: RethCliExt> Commands<Ext> {\n-    /// Sets the node extension if it is the [NodeCommand](node::NodeCommand).\n-    ///\n-    /// This is a noop if the command is not the [NodeCommand](node::NodeCommand).\n-    pub fn set_node_extension(&mut self, ext: Ext::Node) {\n-        if let Commands::Node(command) = self {\n-            command.ext = ext\n-        }\n-    }\n-}\n-\n #[cfg(test)]\n mod tests {\n     use super::*;\n@@ -174,7 +212,7 @@ mod tests {\n \n     #[test]\n     fn parse_color_mode() {\n-        let reth = Cli::<()>::try_parse_from([\"reth\", \"node\", \"--color\", \"always\"]).unwrap();\n+        let reth = Cli::try_parse_args_from([\"reth\", \"node\", \"--color\", \"always\"]).unwrap();\n         assert_eq!(reth.logs.color, ColorMode::Always);\n     }\n \n@@ -183,9 +221,9 @@ mod tests {\n     /// runtime\n     #[test]\n     fn test_parse_help_all_subcommands() {\n-        let reth = Cli::<()>::command();\n+        let reth = Cli::<NoArgs>::command();\n         for sub_command in reth.get_subcommands() {\n-            let err = Cli::<()>::try_parse_from([\"reth\", sub_command.get_name(), \"--help\"])\n+            let err = Cli::try_parse_args_from([\"reth\", sub_command.get_name(), \"--help\"])\n                 .err()\n                 .unwrap_or_else(|| {\n                     panic!(\"Failed to parse help message {}\", sub_command.get_name())\n@@ -201,7 +239,7 @@ mod tests {\n     /// name\n     #[test]\n     fn parse_logs_path() {\n-        let mut reth = Cli::<()>::try_parse_from([\"reth\", \"node\"]).unwrap();\n+        let mut reth = Cli::try_parse_args_from([\"reth\", \"node\"]).unwrap();\n         reth.logs.log_file_directory =\n             reth.logs.log_file_directory.join(reth.chain.chain.to_string());\n         let log_dir = reth.logs.log_file_directory;\n@@ -211,7 +249,7 @@ mod tests {\n         let mut iter = SUPPORTED_CHAINS.iter();\n         iter.next();\n         for chain in iter {\n-            let mut reth = Cli::<()>::try_parse_from([\"reth\", \"node\", \"--chain\", chain]).unwrap();\n+            let mut reth = Cli::try_parse_args_from([\"reth\", \"node\", \"--chain\", chain]).unwrap();\n             reth.logs.log_file_directory =\n                 reth.logs.log_file_directory.join(reth.chain.chain.to_string());\n             let log_dir = reth.logs.log_file_directory;\n@@ -220,21 +258,12 @@ mod tests {\n         }\n     }\n \n-    #[test]\n-    fn override_trusted_setup_file() {\n-        // We already have a test that asserts that this has been initialized,\n-        // so we cheat a little bit and check that loading a random file errors.\n-        let reth = Cli::<()>::try_parse_from([\"reth\", \"node\", \"--trusted-setup-file\", \"README.md\"])\n-            .unwrap();\n-        assert!(reth.run().is_err());\n-    }\n-\n     #[test]\n     fn parse_env_filter_directives() {\n         let temp_dir = tempfile::tempdir().unwrap();\n \n         std::env::set_var(\"RUST_LOG\", \"info,evm=debug\");\n-        let reth = Cli::<()>::try_parse_from([\n+        let reth = Cli::try_parse_args_from([\n             \"reth\",\n             \"init\",\n             \"--datadir\",\n@@ -243,6 +272,6 @@ mod tests {\n             \"debug,net=trace\",\n         ])\n         .unwrap();\n-        assert!(reth.run().is_ok());\n+        assert!(reth.run(|_, _| async move { Ok(()) }).is_ok());\n     }\n }"},{"sha":"512df32e85b5d08eac6f42e4bff891a6681794c3","filename":"bin/reth/src/commands/debug_cmd/mod.rs","status":"modified","additions":0,"deletions":2,"changes":2,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Fmod.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Fmod.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Fmod.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -2,9 +2,7 @@\n \n use crate::core::cli::runner::CliContext;\n use clap::{Parser, Subcommand};\n-\n mod build_block;\n-pub mod engine_api_store;\n mod execution;\n mod in_memory_merkle;\n mod merkle;"},{"sha":"a56ca9cee325bac20f944631c65ac1bedd1cf490","filename":"bin/reth/src/commands/debug_cmd/replay_engine.rs","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Freplay_engine.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Freplay_engine.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fcommands%2Fdebug_cmd%2Freplay_engine.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -4,7 +4,6 @@ use crate::{\n         utils::{chain_help, genesis_value_parser, SUPPORTED_CHAINS},\n         DatabaseArgs, NetworkArgs,\n     },\n-    commands::debug_cmd::engine_api_store::{EngineApiStore, StoredEngineApiMessage},\n     core::cli::runner::CliContext,\n     dirs::{DataDirPath, MaybePlatformPath},\n };\n@@ -20,6 +19,7 @@ use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};\n use reth_interfaces::consensus::Consensus;\n use reth_network::NetworkHandle;\n use reth_network_api::NetworkInfo;\n+use reth_node_core::engine_api_store::{EngineApiStore, StoredEngineApiMessage};\n #[cfg(not(feature = \"optimism\"))]\n use reth_node_ethereum::{EthEngineTypes, EthEvmConfig};\n #[cfg(feature = \"optimism\")]"},{"sha":"f24ebf38d6f0c1c1316a34a2067f04a746f4b2f6","filename":"bin/reth/src/commands/node/mod.rs","status":"modified","additions":75,"deletions":108,"changes":183,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fnode%2Fmod.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fcommands%2Fnode%2Fmod.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fcommands%2Fnode%2Fmod.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,28 +1,24 @@\n-//! Main node command\n-//!\n-//! Starts the client\n+//! Main node command for launching a node\n \n use crate::{\n     args::{\n         utils::{chain_help, genesis_value_parser, parse_socket_address, SUPPORTED_CHAINS},\n         DatabaseArgs, DebugArgs, DevArgs, NetworkArgs, PayloadBuilderArgs, PruningArgs,\n         RpcServerArgs, TxPoolArgs,\n     },\n-    builder::{launch_from_config, NodeConfig},\n-    cli::{db_type::DatabaseBuilder, ext::RethCliExt},\n     core::cli::runner::CliContext,\n     dirs::{DataDirPath, MaybePlatformPath},\n };\n-use clap::{value_parser, Parser};\n-use reth_auto_seal_consensus::AutoSealConsensus;\n-use reth_beacon_consensus::BeaconConsensus;\n-use reth_interfaces::consensus::Consensus;\n+use clap::{value_parser, Args, Parser};\n+use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};\n+use reth_node_builder::{InitState, NodeBuilder, WithLaunchContext};\n+use reth_node_core::node_config::NodeConfig;\n use reth_primitives::ChainSpec;\n-use std::{net::SocketAddr, path::PathBuf, sync::Arc};\n+use std::{ffi::OsString, fmt, future::Future, net::SocketAddr, path::PathBuf, sync::Arc};\n \n /// Start the node\n #[derive(Debug, Parser)]\n-pub struct NodeCommand<Ext: RethCliExt = ()> {\n+pub struct NodeCommand<Ext: clap::Args + fmt::Debug = NoArgs> {\n     /// The path to the data dir for all reth files and subdirectories.\n     ///\n     /// Defaults to the OS-specific data directory:\n@@ -116,63 +112,37 @@ pub struct NodeCommand<Ext: RethCliExt = ()> {\n     #[command(flatten)]\n     pub pruning: PruningArgs,\n \n-    /// Rollup related arguments\n-    #[cfg(feature = \"optimism\")]\n-    #[command(flatten)]\n-    pub rollup: crate::args::RollupArgs,\n-\n     /// Additional cli arguments\n     #[command(flatten, next_help_heading = \"Extension\")]\n-    pub ext: Ext::Node,\n+    pub ext: Ext,\n }\n \n-impl<Ext: RethCliExt> NodeCommand<Ext> {\n-    /// Replaces the extension of the node command\n-    pub fn with_ext<E: RethCliExt>(self, ext: E::Node) -> NodeCommand<E> {\n-        let Self {\n-            datadir,\n-            config,\n-            chain,\n-            metrics,\n-            trusted_setup_file,\n-            instance,\n-            with_unused_ports,\n-            network,\n-            rpc,\n-            txpool,\n-            builder,\n-            debug,\n-            db,\n-            dev,\n-            pruning,\n-            #[cfg(feature = \"optimism\")]\n-            rollup,\n-            ..\n-        } = self;\n-        NodeCommand {\n-            datadir,\n-            config,\n-            chain,\n-            metrics,\n-            instance,\n-            with_unused_ports,\n-            trusted_setup_file,\n-            network,\n-            rpc,\n-            txpool,\n-            builder,\n-            debug,\n-            db,\n-            dev,\n-            pruning,\n-            #[cfg(feature = \"optimism\")]\n-            rollup,\n-            ext,\n-        }\n+impl NodeCommand {\n+    /// Parsers only the default CLI arguments\n+    pub fn parse_args() -> Self {\n+        Self::parse()\n+    }\n+\n+    /// Parsers only the default [NodeCommand] arguments from the given iterator\n+    pub fn try_parse_args_from<I, T>(itr: I) -> Result<Self, clap::error::Error>\n+    where\n+        I: IntoIterator<Item = T>,\n+        T: Into<OsString> + Clone,\n+    {\n+        Self::try_parse_from(itr)\n     }\n+}\n \n-    /// Execute `node` command\n-    pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> {\n+impl<Ext: clap::Args + fmt::Debug> NodeCommand<Ext> {\n+    /// Launches the node\n+    ///\n+    /// This transforms the node command into a node config and launches the node using the given\n+    /// closure.\n+    pub async fn execute<L, Fut>(self, ctx: CliContext, launcher: L) -> eyre::Result<()>\n+    where\n+        L: FnOnce(WithLaunchContext<Arc<DatabaseEnv>, InitState>, Ext) -> Fut,\n+        Fut: Future<Output = eyre::Result<()>>,\n+    {\n         let Self {\n             datadir,\n             config,\n@@ -189,17 +159,11 @@ impl<Ext: RethCliExt> NodeCommand<Ext> {\n             db,\n             dev,\n             pruning,\n-            #[cfg(feature = \"optimism\")]\n-            rollup,\n             ext,\n         } = self;\n \n-        // set up real database\n-        let database = DatabaseBuilder::Real(datadir);\n-\n         // set up node config\n         let mut node_config = NodeConfig {\n-            database,\n             config,\n             chain,\n             metrics,\n@@ -213,35 +177,38 @@ impl<Ext: RethCliExt> NodeCommand<Ext> {\n             db,\n             dev,\n             pruning,\n-            #[cfg(feature = \"optimism\")]\n-            rollup,\n         };\n \n+        // Register the prometheus recorder before creating the database,\n+        // because database init needs it to register metrics.\n+        let _ = node_config.install_prometheus_recorder()?;\n+\n+        let data_dir = datadir.unwrap_or_chain_default(node_config.chain.chain);\n+        let db_path = data_dir.db_path();\n+\n+        tracing::info!(target: \"reth::cli\", path = ?db_path, \"Opening database\");\n+        let database = Arc::new(\n+            init_db(db_path.clone(), DatabaseArguments::default().log_level(db.log_level))?\n+                .with_metrics(),\n+        );\n+\n         if with_unused_ports {\n             node_config = node_config.with_unused_ports();\n         }\n \n-        let executor = ctx.task_executor;\n-\n-        // launch the node\n-        let handle = launch_from_config::<Ext>(node_config, ext, executor).await?;\n+        let builder = NodeBuilder::new(node_config)\n+            .with_database(database)\n+            .with_launch_context(ctx.task_executor, data_dir);\n \n-        handle.wait_for_node_exit().await\n-    }\n-\n-    /// Returns the [Consensus] instance to use.\n-    ///\n-    /// By default this will be a [BeaconConsensus] instance, but if the `--dev` flag is set, it\n-    /// will be an [AutoSealConsensus] instance.\n-    pub fn consensus(&self) -> Arc<dyn Consensus> {\n-        if self.dev.dev {\n-            Arc::new(AutoSealConsensus::new(Arc::clone(&self.chain)))\n-        } else {\n-            Arc::new(BeaconConsensus::new(Arc::clone(&self.chain)))\n-        }\n+        launcher(builder, ext).await\n     }\n }\n \n+/// No Additional arguments\n+#[derive(Debug, Clone, Copy, Default, Args)]\n+#[non_exhaustive]\n+pub struct NoArgs;\n+\n #[cfg(test)]\n mod tests {\n     use super::*;\n@@ -253,28 +220,28 @@ mod tests {\n \n     #[test]\n     fn parse_help_node_command() {\n-        let err = NodeCommand::<()>::try_parse_from([\"reth\", \"--help\"]).unwrap_err();\n+        let err = NodeCommand::try_parse_args_from([\"reth\", \"--help\"]).unwrap_err();\n         assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp);\n     }\n \n     #[test]\n     fn parse_common_node_command_chain_args() {\n         for chain in SUPPORTED_CHAINS {\n-            let args: NodeCommand = NodeCommand::<()>::parse_from([\"reth\", \"--chain\", chain]);\n+            let args: NodeCommand = NodeCommand::<NoArgs>::parse_from([\"reth\", \"--chain\", chain]);\n             assert_eq!(args.chain.chain, chain.parse::<reth_primitives::Chain>().unwrap());\n         }\n     }\n \n     #[test]\n     fn parse_discovery_addr() {\n         let cmd =\n-            NodeCommand::<()>::try_parse_from([\"reth\", \"--discovery.addr\", \"127.0.0.1\"]).unwrap();\n+            NodeCommand::try_parse_args_from([\"reth\", \"--discovery.addr\", \"127.0.0.1\"]).unwrap();\n         assert_eq!(cmd.network.discovery.addr, Ipv4Addr::LOCALHOST);\n     }\n \n     #[test]\n     fn parse_addr() {\n-        let cmd = NodeCommand::<()>::try_parse_from([\n+        let cmd = NodeCommand::try_parse_args_from([\n             \"reth\",\n             \"--discovery.addr\",\n             \"127.0.0.1\",\n@@ -288,42 +255,42 @@ mod tests {\n \n     #[test]\n     fn parse_discovery_port() {\n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\", \"--discovery.port\", \"300\"]).unwrap();\n+        let cmd = NodeCommand::try_parse_args_from([\"reth\", \"--discovery.port\", \"300\"]).unwrap();\n         assert_eq!(cmd.network.discovery.port, 300);\n     }\n \n     #[test]\n     fn parse_port() {\n         let cmd =\n-            NodeCommand::<()>::try_parse_from([\"reth\", \"--discovery.port\", \"300\", \"--port\", \"99\"])\n+            NodeCommand::try_parse_args_from([\"reth\", \"--discovery.port\", \"300\", \"--port\", \"99\"])\n                 .unwrap();\n         assert_eq!(cmd.network.discovery.port, 300);\n         assert_eq!(cmd.network.port, 99);\n     }\n \n     #[test]\n     fn parse_metrics_port() {\n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\", \"--metrics\", \"9001\"]).unwrap();\n+        let cmd = NodeCommand::try_parse_args_from([\"reth\", \"--metrics\", \"9001\"]).unwrap();\n         assert_eq!(cmd.metrics, Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9001)));\n \n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\", \"--metrics\", \":9001\"]).unwrap();\n+        let cmd = NodeCommand::try_parse_args_from([\"reth\", \"--metrics\", \":9001\"]).unwrap();\n         assert_eq!(cmd.metrics, Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9001)));\n \n         let cmd =\n-            NodeCommand::<()>::try_parse_from([\"reth\", \"--metrics\", \"localhost:9001\"]).unwrap();\n+            NodeCommand::try_parse_args_from([\"reth\", \"--metrics\", \"localhost:9001\"]).unwrap();\n         assert_eq!(cmd.metrics, Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9001)));\n     }\n \n     #[test]\n     fn parse_config_path() {\n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\", \"--config\", \"my/path/to/reth.toml\"])\n-            .unwrap();\n+        let cmd =\n+            NodeCommand::try_parse_args_from([\"reth\", \"--config\", \"my/path/to/reth.toml\"]).unwrap();\n         // always store reth.toml in the data dir, not the chain specific data dir\n         let data_dir = cmd.datadir.unwrap_or_chain_default(cmd.chain.chain);\n         let config_path = cmd.config.unwrap_or(data_dir.config_path());\n         assert_eq!(config_path, Path::new(\"my/path/to/reth.toml\"));\n \n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\"]).unwrap();\n+        let cmd = NodeCommand::try_parse_args_from([\"reth\"]).unwrap();\n \n         // always store reth.toml in the data dir, not the chain specific data dir\n         let data_dir = cmd.datadir.unwrap_or_chain_default(cmd.chain.chain);\n@@ -334,14 +301,14 @@ mod tests {\n \n     #[test]\n     fn parse_db_path() {\n-        let cmd = NodeCommand::<()>::try_parse_from([\"reth\"]).unwrap();\n+        let cmd = NodeCommand::try_parse_args_from([\"reth\"]).unwrap();\n         let data_dir = cmd.datadir.unwrap_or_chain_default(cmd.chain.chain);\n         let db_path = data_dir.db_path();\n         let end = format!(\"reth/{}/db\", SUPPORTED_CHAINS[0]);\n         assert!(db_path.ends_with(end), \"{:?}\", cmd.config);\n \n         let cmd =\n-            NodeCommand::<()>::try_parse_from([\"reth\", \"--datadir\", \"my/custom/path\"]).unwrap();\n+            NodeCommand::try_parse_args_from([\"reth\", \"--datadir\", \"my/custom/path\"]).unwrap();\n         let data_dir = cmd.datadir.unwrap_or_chain_default(cmd.chain.chain);\n         let db_path = data_dir.db_path();\n         assert_eq!(db_path, Path::new(\"my/custom/path/db\"));\n@@ -350,7 +317,7 @@ mod tests {\n     #[test]\n     #[cfg(not(feature = \"optimism\"))] // dev mode not yet supported in op-reth\n     fn parse_dev() {\n-        let cmd = NodeCommand::<()>::parse_from([\"reth\", \"--dev\"]);\n+        let cmd = NodeCommand::<NoArgs>::parse_from([\"reth\", \"--dev\"]);\n         let chain = reth_primitives::DEV.clone();\n         assert_eq!(cmd.chain.chain, chain.chain);\n         assert_eq!(cmd.chain.genesis_hash, chain.genesis_hash);\n@@ -368,7 +335,7 @@ mod tests {\n \n     #[test]\n     fn parse_instance() {\n-        let mut cmd = NodeCommand::<()>::parse_from([\"reth\"]);\n+        let mut cmd = NodeCommand::<NoArgs>::parse_from([\"reth\"]);\n         cmd.rpc.adjust_instance_ports(cmd.instance);\n         cmd.network.port = DEFAULT_DISCOVERY_PORT + cmd.instance - 1;\n         // check rpc port numbers\n@@ -378,7 +345,7 @@ mod tests {\n         // check network listening port number\n         assert_eq!(cmd.network.port, 30303);\n \n-        let mut cmd = NodeCommand::<()>::parse_from([\"reth\", \"--instance\", \"2\"]);\n+        let mut cmd = NodeCommand::<NoArgs>::parse_from([\"reth\", \"--instance\", \"2\"]);\n         cmd.rpc.adjust_instance_ports(cmd.instance);\n         cmd.network.port = DEFAULT_DISCOVERY_PORT + cmd.instance - 1;\n         // check rpc port numbers\n@@ -388,7 +355,7 @@ mod tests {\n         // check network listening port number\n         assert_eq!(cmd.network.port, 30304);\n \n-        let mut cmd = NodeCommand::<()>::parse_from([\"reth\", \"--instance\", \"3\"]);\n+        let mut cmd = NodeCommand::<NoArgs>::parse_from([\"reth\", \"--instance\", \"3\"]);\n         cmd.rpc.adjust_instance_ports(cmd.instance);\n         cmd.network.port = DEFAULT_DISCOVERY_PORT + cmd.instance - 1;\n         // check rpc port numbers\n@@ -401,21 +368,21 @@ mod tests {\n \n     #[test]\n     fn parse_with_unused_ports() {\n-        let cmd = NodeCommand::<()>::parse_from([\"reth\", \"--with-unused-ports\"]);\n+        let cmd = NodeCommand::<NoArgs>::parse_from([\"reth\", \"--with-unused-ports\"]);\n         assert!(cmd.with_unused_ports);\n     }\n \n     #[test]\n     fn with_unused_ports_conflicts_with_instance() {\n         let err =\n-            NodeCommand::<()>::try_parse_from([\"reth\", \"--with-unused-ports\", \"--instance\", \"2\"])\n+            NodeCommand::try_parse_args_from([\"reth\", \"--with-unused-ports\", \"--instance\", \"2\"])\n                 .unwrap_err();\n         assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);\n     }\n \n     #[test]\n     fn with_unused_ports_check_zero() {\n-        let mut cmd = NodeCommand::<()>::parse_from([\"reth\"]);\n+        let mut cmd = NodeCommand::<NoArgs>::parse_from([\"reth\"]);\n         cmd.rpc = cmd.rpc.with_unused_ports();\n         cmd.network = cmd.network.with_unused_ports();\n "},{"sha":"edfeabf23ef91e68f8f6b0f7b9ec8c5fb142af59","filename":"bin/reth/src/lib.rs","status":"modified","additions":5,"deletions":1,"changes":6,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -26,7 +26,6 @@\n )]\n #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]\n \n-pub mod builder;\n pub mod cli;\n pub mod commands;\n pub mod utils;\n@@ -62,6 +61,11 @@ pub mod version {\n     pub use reth_node_core::version::*;\n }\n \n+/// Re-exported from `reth_node_builder`\n+pub mod builder {\n+    pub use reth_node_builder::*;\n+}\n+\n /// Re-exported from `reth_node_core`, also to prevent a breaking change. See the comment on\n /// the `reth_node_core::args` re-export for more details.\n pub mod dirs {"},{"sha":"609c7ad1dec7031cdcb530dbd7e28169767c6cc9","filename":"bin/reth/src/main.rs","status":"modified","additions":7,"deletions":1,"changes":8,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -10,12 +10,18 @@ compile_error!(\"Cannot build the `reth` binary with the `optimism` feature flag\n \n #[cfg(not(feature = \"optimism\"))]\n fn main() {\n+    use reth::cli::Cli;\n+    use reth_node_ethereum::EthereumNode;\n+\n     // Enable backtraces unless a RUST_BACKTRACE value has already been explicitly provided.\n     if std::env::var(\"RUST_BACKTRACE\").is_err() {\n         std::env::set_var(\"RUST_BACKTRACE\", \"1\");\n     }\n \n-    if let Err(err) = reth::cli::run() {\n+    if let Err(err) = Cli::parse_args().run(|builder, _| async {\n+        let handle = builder.launch_node(EthereumNode::default()).await?;\n+        handle.node_exit_future.await\n+    }) {\n         eprintln!(\"Error: {err:?}\");\n         std::process::exit(1);\n     }"},{"sha":"9799d19a6fee06a1b66d1236fe6e06ec2b93a345","filename":"bin/reth/src/optimism.rs","status":"modified","additions":35,"deletions":1,"changes":36,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Foptimism.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/bin%2Freth%2Fsrc%2Foptimism.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/bin%2Freth%2Fsrc%2Foptimism.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,4 +1,11 @@\n #![allow(missing_docs, rustdoc::missing_crate_level_docs)]\n+\n+use clap::Parser;\n+use reth::cli::Cli;\n+use reth_node_builder::NodeHandle;\n+use reth_node_optimism::{args::RollupArgs, OptimismEngineTypes, OptimismNode};\n+use reth_provider::BlockReaderIdExt;\n+\n // We use jemalloc for performance reasons\n #[cfg(all(feature = \"jemalloc\", unix))]\n #[global_allocator]\n@@ -14,7 +21,34 @@ fn main() {\n         std::env::set_var(\"RUST_BACKTRACE\", \"1\");\n     }\n \n-    if let Err(err) = reth::cli::run() {\n+    if let Err(err) = Cli::<RollupArgs>::parse().run(|builder, rollup_args| async move {\n+        let NodeHandle { node, node_exit_future } =\n+            builder.launch_node(OptimismNode::new(rollup_args.clone())).await?;\n+\n+        // If `enable_genesis_walkback` is set to true, the rollup client will need to\n+        // perform the derivation pipeline from genesis, validating the data dir.\n+        // When set to false, set the finalized, safe, and unsafe head block hashes\n+        // on the rollup client using a fork choice update. This prevents the rollup\n+        // client from performing the derivation pipeline from genesis, and instead\n+        // starts syncing from the current tip in the DB.\n+        if node.chain_spec().is_optimism() && !rollup_args.enable_genesis_walkback {\n+            let client = node.rpc_server_handles.auth.http_client();\n+            if let Ok(Some(head)) = node.provider.latest_header() {\n+                reth_rpc_api::EngineApiClient::<OptimismEngineTypes>::fork_choice_updated_v2(\n+                    &client,\n+                    reth_rpc_types::engine::ForkchoiceState {\n+                        head_block_hash: head.hash(),\n+                        safe_block_hash: head.hash(),\n+                        finalized_block_hash: head.hash(),\n+                    },\n+                    None,\n+                )\n+                .await?;\n+            }\n+        }\n+\n+        node_exit_future.await\n+    }) {\n         eprintln!(\"Error: {err:?}\");\n         std::process::exit(1);\n     }"},{"sha":"62ef0e9f12297d789a4e494df0b963ac87e9a5aa","filename":"crates/consensus/auto-seal/Cargo.toml","status":"modified","additions":0,"deletions":9,"changes":9,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fconsensus%2Fauto-seal%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fconsensus%2Fauto-seal%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fconsensus%2Fauto-seal%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -28,15 +28,6 @@ tokio = { workspace = true, features = [\"sync\", \"time\"] }\n tokio-stream.workspace = true\n tracing.workspace = true\n \n-[dev-dependencies]\n-reth-interfaces = { workspace = true, features = [\"test-utils\"] }\n-reth.workspace = true\n-tempfile.workspace = true\n-clap.workspace = true\n-jsonrpsee.workspace = true\n-eyre.workspace = true\n-serde_json.workspace = true\n-\n [features]\n # Included solely to ignore certain tests.\n optimism = []"},{"sha":"bb24e7f50ec3f3319013228c664baf7d7080698a","filename":"crates/consensus/auto-seal/src/lib.rs","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fconsensus%2Fauto-seal%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fconsensus%2Fauto-seal%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fconsensus%2Fauto-seal%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -13,6 +13,7 @@\n     issue_tracker_base_url = \"https://github.com/paradigmxyz/reth/issues/\"\n )]\n #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]\n+#![warn(unused_crate_dependencies)]\n \n use reth_beacon_consensus::BeaconEngineMessage;\n use reth_interfaces::{"},{"sha":"681968f1be88662e0140db59e7bb433d7e69ecf8","filename":"crates/consensus/auto-seal/tests/it/auto_mine.rs","status":"removed","additions":0,"deletions":125,"changes":125,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fauto_mine.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fauto_mine.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fauto_mine.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,125 +0,0 @@\n-//! auto-mine consensus integration test\n-\n-use clap::Parser;\n-use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder, rpc_params};\n-use reth::{\n-    cli::{\n-        components::RethNodeComponents,\n-        ext::{NoArgs, NoArgsCliExt, RethNodeCommandConfig},\n-    },\n-    commands::node::NodeCommand,\n-    core::cli::runner::CliRunner,\n-    tasks::TaskSpawner,\n-};\n-use reth_primitives::{hex, revm_primitives::FixedBytes, ChainSpec, Genesis};\n-use reth_provider::CanonStateSubscriptions;\n-use reth_transaction_pool::TransactionPool;\n-use std::{sync::Arc, time::Duration};\n-use tokio::time::timeout;\n-\n-#[derive(Debug)]\n-struct AutoMineConfig;\n-\n-impl RethNodeCommandConfig for AutoMineConfig {\n-    fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {\n-        let pool = components.pool();\n-        let mut canon_events = components.events().subscribe_to_canonical_state();\n-\n-        components.task_executor().spawn_critical_blocking(\"rpc request\", Box::pin(async move {\n-            // submit tx through rpc\n-            let raw_tx = \"0x02f876820a28808477359400847735940082520894ab0840c0e43688012c1adb0f5e3fc665188f83d28a029d394a5d630544000080c080a0a044076b7e67b5deecc63f61a8d7913fab86ca365b344b5759d1fe3563b4c39ea019eab979dd000da04dfc72bb0377c092d30fd9e1cab5ae487de49586cc8b0090\";\n-            let client = HttpClientBuilder::default().build(\"http://127.0.0.1:8545\").expect(\"http client should bind to default rpc port\");\n-            let response: String = client.request(\"eth_sendRawTransaction\", rpc_params![raw_tx]).await.expect(\"client request should be valid\");\n-            let expected = \"0xb1c6512f4fc202c04355fbda66755e0e344b152e633010e8fd75ecec09b63398\";\n-\n-            assert_eq!(&response, expected);\n-\n-            // more than enough time for the next block\n-            let duration = Duration::from_secs(15);\n-\n-            // wait for canon event or timeout\n-            let update = timeout(duration, canon_events.recv())\n-                .await\n-                .expect(\"canon state should change before timeout\")\n-                .expect(\"canon events stream is still open\");\n-            let new_tip = update.tip();\n-            let expected_tx_root: FixedBytes<32> = hex!(\"c79b5383458e63fb20c6a49d9ec7917195a59003a2af4b28a01d7c6fbbcd7e35\").into();\n-            assert_eq!(new_tip.transactions_root, expected_tx_root);\n-            assert_eq!(new_tip.number, 1);\n-            assert!(pool.pending_transactions().is_empty());\n-        }));\n-        Ok(())\n-    }\n-}\n-\n-/// This test is disabled for the `optimism` feature flag due to an incompatible feature set.\n-/// L1 info transactions are not included automatically, which are required for `op-reth` to\n-/// process transactions.\n-#[test]\n-#[cfg_attr(feature = \"optimism\", ignore)]\n-pub(crate) fn test_auto_mine() {\n-    // create temp path for test\n-    let temp_path = tempfile::TempDir::new().expect(\"tempdir is okay\").into_path();\n-    let datadir = temp_path.to_str().expect(\"temp path is okay\");\n-\n-    let no_args = NoArgs::with(AutoMineConfig);\n-    let chain = custom_chain();\n-    let mut command = NodeCommand::<NoArgsCliExt<AutoMineConfig>>::parse_from([\n-        \"reth\",\n-        \"--dev\",\n-        \"--datadir\",\n-        datadir,\n-        \"--debug.max-block\",\n-        \"1\",\n-        \"--debug.terminate\",\n-    ])\n-    .with_ext::<NoArgsCliExt<AutoMineConfig>>(no_args);\n-\n-    // use custom chain spec\n-    command.chain = chain;\n-\n-    let runner = CliRunner::default();\n-    let node_command = runner.run_command_until_exit(|ctx| command.execute(ctx));\n-    assert!(node_command.is_ok())\n-}\n-\n-fn custom_chain() -> Arc<ChainSpec> {\n-    let custom_genesis = r#\"\n-{\n-    \"nonce\": \"0x42\",\n-    \"timestamp\": \"0x0\",\n-    \"extraData\": \"0x5343\",\n-    \"gasLimit\": \"0x1388\",\n-    \"difficulty\": \"0x400000000\",\n-    \"mixHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n-    \"coinbase\": \"0x0000000000000000000000000000000000000000\",\n-    \"alloc\": {\n-        \"0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b\": {\n-            \"balance\": \"0x4a47e3c12448f4ad000000\"\n-        }\n-    },\n-    \"number\": \"0x0\",\n-    \"gasUsed\": \"0x0\",\n-    \"parentHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n-    \"config\": {\n-        \"ethash\": {},\n-        \"chainId\": 2600,\n-        \"homesteadBlock\": 0,\n-        \"eip150Block\": 0,\n-        \"eip155Block\": 0,\n-        \"eip158Block\": 0,\n-        \"byzantiumBlock\": 0,\n-        \"constantinopleBlock\": 0,\n-        \"petersburgBlock\": 0,\n-        \"istanbulBlock\": 0,\n-        \"berlinBlock\": 0,\n-        \"londonBlock\": 0,\n-        \"terminalTotalDifficulty\": 0,\n-        \"terminalTotalDifficultyPassed\": true,\n-        \"shanghaiTime\": 0\n-    }\n-}\n-\"#;\n-    let genesis: Genesis = serde_json::from_str(custom_genesis).unwrap();\n-    Arc::new(genesis.into())\n-}"},{"sha":"5d070481791de22f09fce60436f4364caad9743a","filename":"crates/consensus/auto-seal/tests/it/main.rs","status":"removed","additions":0,"deletions":4,"changes":4,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fconsensus%2Fauto-seal%2Ftests%2Fit%2Fmain.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,4 +0,0 @@\n-//! auto-mine consensus tests\n-mod auto_mine;\n-\n-async fn main() {}"},{"sha":"9b43e52f21b003694272c27e40eda1106f256f45","filename":"crates/node-builder/src/builder.rs","status":"modified","additions":428,"deletions":92,"changes":520,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fbuilder.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fbuilder.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fbuilder.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -4,32 +4,33 @@\n \n use crate::{\n     components::{\n-        FullNodeComponents, FullNodeComponentsAdapter, NodeComponents, NodeComponentsBuilder,\n+        ComponentsBuilder, FullNodeComponents, FullNodeComponentsAdapter, NodeComponents,\n+        NodeComponentsBuilder, PoolBuilder,\n     },\n     hooks::NodeHooks,\n     node::{FullNode, FullNodeTypes, FullNodeTypesAdapter, NodeTypes},\n     rpc::{RethRpcServerHandles, RpcContext, RpcHooks},\n-    NodeHandle,\n+    Node, NodeHandle,\n };\n use eyre::Context;\n use futures::{future::Either, stream, stream_select, StreamExt};\n use reth_beacon_consensus::{\n-    hooks::{EngineHooks, PruneHook},\n+    hooks::{EngineHooks, PruneHook, StaticFileHook},\n     BeaconConsensusEngine,\n };\n use reth_blockchain_tree::{BlockchainTreeConfig, ShareableBlockchainTree};\n use reth_db::{\n     database::Database,\n     database_metrics::{DatabaseMetadata, DatabaseMetrics},\n+    test_utils::{create_test_rw_db, TempDatabase},\n+    DatabaseEnv,\n };\n use reth_interfaces::p2p::either::EitherDownloader;\n-use reth_network::{\n-    transactions::{TransactionFetcherConfig, TransactionsManagerConfig},\n-    NetworkBuilder, NetworkEvents, NetworkHandle,\n-};\n+use reth_network::{NetworkBuilder, NetworkConfig, NetworkEvents, NetworkHandle};\n use reth_node_core::{\n     cli::config::{PayloadBuilderConfig, RethRpcConfig, RethTransactionPoolConfig},\n-    dirs::{ChainPath, DataDirPath},\n+    dirs::{ChainPath, DataDirPath, MaybePlatformPath},\n+    engine_api_store::EngineApiStore,\n     events::cl::ConsensusLayerHealthEvents,\n     exit::NodeExitFuture,\n     init::init_genesis,\n@@ -42,20 +43,24 @@ use reth_primitives::{\n     format_ether, ChainSpec,\n };\n use reth_provider::{providers::BlockchainProvider, ChainSpecProvider, ProviderFactory};\n-use reth_prune::{PrunerBuilder, PrunerEvent};\n+use reth_prune::PrunerBuilder;\n use reth_revm::EvmProcessorFactory;\n use reth_rpc_engine_api::EngineApi;\n+use reth_static_file::StaticFileProducer;\n use reth_tasks::TaskExecutor;\n use reth_tracing::tracing::{debug, info};\n use reth_transaction_pool::{PoolConfig, TransactionPool};\n-use std::sync::Arc;\n+use std::{str::FromStr, sync::Arc};\n use tokio::sync::{mpsc::unbounded_channel, oneshot};\n \n /// The builtin provider type of the reth node.\n // Note: we need to hardcode this because custom components might depend on it in associated types.\n type RethFullProviderType<DB, Evm> =\n     BlockchainProvider<DB, ShareableBlockchainTree<DB, EvmProcessorFactory<Evm>>>;\n \n+type RethFullAdapter<DB, N> =\n+    FullNodeTypesAdapter<N, DB, RethFullProviderType<DB, <N as NodeTypes>::Evm>>;\n+\n /// Declaratively construct a node.\n ///\n /// [`NodeBuilder`] provides a [builder-like interface][builder] for composing\n@@ -69,11 +74,19 @@ type RethFullProviderType<DB, Evm> =\n /// [ConfigureEvm](reth_node_api::evm::ConfigureEvm), the database [Database] and finally all the\n /// components of the node that are downstream of those types, these include:\n ///\n-///  - The transaction pool: [PoolBuilder](crate::components::PoolBuilder)\n+///  - The transaction pool: [PoolBuilder]\n ///  - The network: [NetworkBuilder](crate::components::NetworkBuilder)\n ///  - The payload builder: [PayloadBuilder](crate::components::PayloadServiceBuilder)\n ///\n-/// Finally, the node is ready to launch [NodeBuilder::launch]\n+/// Once all the components are configured, the node is ready to be launched.\n+///\n+/// On launch the builder returns a fully type aware [NodeHandle] that has access to all the\n+/// configured components and can interact with the node.\n+///\n+/// There are convenience functions for networks that come with a preset of types and components via\n+/// the [Node] trait, see `reth_node_ethereum::EthereumNode` or `reth_node_optimism::OptimismNode`.\n+///\n+/// The [NodeBuilder::node] function configures the node's types and components in one step.\n ///\n /// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html\n pub struct NodeBuilder<DB, State> {\n@@ -122,15 +135,40 @@ impl NodeBuilder<(), InitState> {\n }\n \n impl<DB> NodeBuilder<DB, InitState> {\n-    /// Configures the additional external context, e.g. additional context captured via CLI args.\n+    /// Configures the underlying database that the node will use.\n     pub fn with_database<D>(self, database: D) -> NodeBuilder<D, InitState> {\n         NodeBuilder { config: self.config, state: self.state, database }\n     }\n+\n+    /// Preconfigure the builder with the context to launch the node.\n+    ///\n+    /// This provides the task executor and the data directory for the node.\n+    pub fn with_launch_context(\n+        self,\n+        task_executor: TaskExecutor,\n+        data_dir: ChainPath<DataDirPath>,\n+    ) -> WithLaunchContext<DB, InitState> {\n+        WithLaunchContext { builder: self, task_executor, data_dir }\n+    }\n+\n+    /// Creates an _ephemeral_ preconfigured node for testing purposes.\n+    pub fn testing_node(\n+        self,\n+        task_executor: TaskExecutor,\n+    ) -> WithLaunchContext<Arc<TempDatabase<DatabaseEnv>>, InitState> {\n+        let db = create_test_rw_db();\n+        let db_path_str = db.path().to_str().expect(\"Path is not valid unicode\");\n+        let path =\n+            MaybePlatformPath::<DataDirPath>::from_str(db_path_str).expect(\"Path is not valid\");\n+        let data_dir = path.unwrap_or_chain_default(self.config.chain.chain);\n+\n+        WithLaunchContext { builder: self.with_database(db), task_executor, data_dir }\n+    }\n }\n \n impl<DB> NodeBuilder<DB, InitState>\n where\n-    DB: Database + Clone + 'static,\n+    DB: Database + Unpin + Clone + 'static,\n {\n     /// Configures the types of the node.\n     pub fn with_types<T>(self, types: T) -> NodeBuilder<DB, TypesState<T, DB>>\n@@ -143,6 +181,43 @@ where\n             database: self.database,\n         }\n     }\n+\n+    /// Preconfigures the node with a specific node implementation.\n+    ///\n+    /// This is a convenience method that sets the node's types and components in one call.\n+    pub fn node<N>(\n+        self,\n+        node: N,\n+    ) -> NodeBuilder<\n+        DB,\n+        ComponentsState<\n+            N,\n+            ComponentsBuilder<\n+                RethFullAdapter<DB, N>,\n+                N::PoolBuilder,\n+                N::PayloadBuilder,\n+                N::NetworkBuilder,\n+            >,\n+            FullNodeComponentsAdapter<\n+                RethFullAdapter<DB, N>,\n+                <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+            >,\n+        >,\n+    >\n+    where\n+        N: Node<FullNodeTypesAdapter<N, DB, RethFullProviderType<DB, <N as NodeTypes>::Evm>>>,\n+        N::PoolBuilder: PoolBuilder<RethFullAdapter<DB, N>>,\n+        N::NetworkBuilder: crate::components::NetworkBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+        N::PayloadBuilder: crate::components::PayloadServiceBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+    {\n+        self.with_types(node.clone()).with_components(node.components())\n+    }\n }\n \n impl<DB, Types> NodeBuilder<DB, TypesState<Types, DB>>\n@@ -216,40 +291,6 @@ where\n         }\n     }\n \n-    /// Resets the setup process to the components stage.\n-    ///\n-    /// CAUTION: All previously configured hooks will be lost.\n-    pub fn fuse_components<C>(\n-        self,\n-        components_builder: C,\n-    ) -> NodeBuilder<\n-        DB,\n-        ComponentsState<\n-            Types,\n-            C,\n-            FullNodeComponentsAdapter<\n-                FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n-                C::Pool,\n-            >,\n-        >,\n-    >\n-    where\n-        C: NodeComponentsBuilder<\n-            FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n-        >,\n-    {\n-        NodeBuilder {\n-            config: self.config,\n-            database: self.database,\n-            state: ComponentsState {\n-                types: self.state.types,\n-                components_builder,\n-                hooks: NodeHooks::new(),\n-                rpc: RpcHooks::new(),\n-            },\n-        }\n-    }\n-\n     /// Sets the hook that is run once the node's components are initialized.\n     pub fn on_component_initialized<F>(mut self, hook: F) -> Self\n     where\n@@ -259,6 +300,7 @@ where\n                     Components::Pool,\n                 >,\n             ) -> eyre::Result<()>\n+            + Send\n             + 'static,\n     {\n         self.state.hooks.set_on_component_initialized(hook);\n@@ -276,6 +318,7 @@ where\n                     >,\n                 >,\n             ) -> eyre::Result<()>\n+            + Send\n             + 'static,\n     {\n         self.state.hooks.set_on_node_started(hook);\n@@ -295,6 +338,7 @@ where\n                 >,\n                 RethRpcServerHandles,\n             ) -> eyre::Result<()>\n+            + Send\n             + 'static,\n     {\n         self.state.rpc.set_on_rpc_started(hook);\n@@ -313,13 +357,19 @@ where\n                     >,\n                 >,\n             ) -> eyre::Result<()>\n+            + Send\n             + 'static,\n     {\n         self.state.rpc.set_extend_rpc_modules(hook);\n         self\n     }\n \n     /// Launches the node and returns a handle to it.\n+    ///\n+    /// This bootstraps the node internals, creates all the components with the provider\n+    /// [NodeComponentsBuilder] and launches the node.\n+    ///\n+    /// Returns a [NodeHandle] that can be used to interact with the node.\n     pub async fn launch(\n         self,\n         executor: TaskExecutor,\n@@ -332,7 +382,7 @@ where\n             >,\n         >,\n     > {\n-        // get config\n+        // get config from file\n         let reth_config = self.load_config(&data_dir)?;\n \n         let Self {\n@@ -354,20 +404,14 @@ where\n             database.clone(),\n             Arc::clone(&config.chain),\n             data_dir.static_files_path(),\n-        )?;\n-\n-        // configure static_file_producer\n-        let static_file_producer = reth_static_file::StaticFileProducer::new(\n-            provider_factory.clone(),\n-            provider_factory.static_file_provider(),\n-            config.prune_config()?.unwrap_or_default().segments,\n-        );\n+        )?\n+        .with_static_files_metrics();\n \n         debug!(target: \"reth::cli\", chain=%config.chain.chain, genesis=?config.chain.genesis_hash(), \"Initializing genesis\");\n \n         let genesis_hash = init_genesis(provider_factory.clone())?;\n \n-        info!(target: \"reth::cli\", \"{}\", config.chain.display_hardforks());\n+        info!(target: \"reth::cli\", \"{}\",config.chain.display_hardforks());\n \n         let consensus = config.consensus();\n \n@@ -412,7 +456,7 @@ where\n \n         debug!(target: \"reth::cli\", \"creating components\");\n         let NodeComponents { transaction_pool, network, payload_builder } =\n-            components_builder.build_components(&ctx)?;\n+            components_builder.build_components(&ctx).await?;\n \n         let BuilderContext {\n             provider: blockchain_db,\n@@ -438,8 +482,30 @@ where\n \n         // create pipeline\n         let network_client = network.fetch_client().await?;\n-        let (consensus_engine_tx, consensus_engine_rx) = unbounded_channel();\n+        let (consensus_engine_tx, mut consensus_engine_rx) = unbounded_channel();\n+\n+        if let Some(store_path) = config.debug.engine_api_store.clone() {\n+            debug!(target: \"reth::cli\", \"spawning engine API store\");\n+            let (engine_intercept_tx, engine_intercept_rx) = unbounded_channel();\n+            let engine_api_store = EngineApiStore::new(store_path);\n+            executor.spawn_critical(\n+                \"engine api interceptor\",\n+                engine_api_store.intercept(consensus_engine_rx, engine_intercept_tx),\n+            );\n+            consensus_engine_rx = engine_intercept_rx;\n+        };\n+\n         let max_block = config.max_block(&network_client, provider_factory.clone()).await?;\n+        let mut hooks = EngineHooks::new();\n+\n+        let mut static_file_producer = StaticFileProducer::new(\n+            provider_factory.clone(),\n+            provider_factory.static_file_provider(),\n+            prune_config.clone().unwrap_or_default().segments,\n+        );\n+        let static_file_producer_events = static_file_producer.events();\n+        hooks.add(StaticFileHook::new(static_file_producer.clone(), Box::new(executor.clone())));\n+        info!(target: \"reth::cli\", \"StaticFileProducer initialized\");\n \n         // Configure the pipeline\n         let (mut pipeline, client) = if config.dev.dev {\n@@ -504,22 +570,16 @@ where\n         let pipeline_events = pipeline.events();\n \n         let initial_target = config.initial_pipeline_target(genesis_hash);\n-        let mut hooks = EngineHooks::new();\n \n-        let pruner_events = if let Some(prune_config) = prune_config {\n-            let mut pruner = PrunerBuilder::new(prune_config.clone())\n-                .max_reorg_depth(tree_config.max_reorg_depth() as usize)\n-                .prune_delete_limit(config.chain.prune_delete_limit)\n-                .build(provider_factory);\n+        let prune_config = prune_config.unwrap_or_default();\n+        let mut pruner = PrunerBuilder::new(prune_config.clone())\n+            .max_reorg_depth(tree_config.max_reorg_depth() as usize)\n+            .prune_delete_limit(config.chain.prune_delete_limit)\n+            .build(provider_factory.clone());\n \n-            let events = pruner.events();\n-            hooks.add(PruneHook::new(pruner, Box::new(executor.clone())));\n-\n-            info!(target: \"reth::cli\", ?prune_config, \"Pruner initialized\");\n-            Either::Left(events)\n-        } else {\n-            Either::Right(stream::empty::<PrunerEvent>())\n-        };\n+        let pruner_events = pruner.events();\n+        hooks.add(PruneHook::new(pruner, Box::new(executor.clone())));\n+        info!(target: \"reth::cli\", ?prune_config, \"Pruner initialized\");\n \n         // Configure the consensus engine\n         let (beacon_consensus_engine, beacon_engine_handle) = BeaconConsensusEngine::with_channel(\n@@ -551,7 +611,8 @@ where\n             } else {\n                 Either::Right(stream::empty())\n             },\n-            pruner_events.map(Into::into)\n+            pruner_events.map(Into::into),\n+            static_file_producer_events.map(Into::into)\n         );\n         executor.spawn_critical(\n             \"events task\",\n@@ -613,7 +674,7 @@ where\n             network,\n             provider,\n             payload_builder,\n-            executor,\n+            task_executor: executor,\n             rpc_server_handles,\n             rpc_registry,\n             config,\n@@ -638,6 +699,283 @@ where\n     }\n }\n \n+/// A [NodeBuilder] with it's launch context already configured.\n+///\n+/// This exposes the same methods as [NodeBuilder] but with the launch context already configured,\n+/// See [WithLaunchContext::launch]\n+pub struct WithLaunchContext<DB, State> {\n+    builder: NodeBuilder<DB, State>,\n+    task_executor: TaskExecutor,\n+    data_dir: ChainPath<DataDirPath>,\n+}\n+\n+impl<DB, State> WithLaunchContext<DB, State> {\n+    /// Returns a reference to the node builder's config.\n+    pub fn config(&self) -> &NodeConfig {\n+        self.builder.config()\n+    }\n+\n+    /// Returns a reference to the task executor.\n+    pub fn task_executor(&self) -> &TaskExecutor {\n+        &self.task_executor\n+    }\n+\n+    /// Returns a reference to the data directory.\n+    pub fn data_dir(&self) -> &ChainPath<DataDirPath> {\n+        &self.data_dir\n+    }\n+}\n+\n+impl<DB> WithLaunchContext<DB, InitState>\n+where\n+    DB: Database + Clone + Unpin + 'static,\n+{\n+    /// Configures the types of the node.\n+    pub fn with_types<T>(self, types: T) -> WithLaunchContext<DB, TypesState<T, DB>>\n+    where\n+        T: NodeTypes,\n+    {\n+        WithLaunchContext {\n+            builder: self.builder.with_types(types),\n+            task_executor: self.task_executor,\n+            data_dir: self.data_dir,\n+        }\n+    }\n+\n+    /// Preconfigures the node with a specific node implementation.\n+    pub fn node<N>(\n+        self,\n+        node: N,\n+    ) -> WithLaunchContext<\n+        DB,\n+        ComponentsState<\n+            N,\n+            ComponentsBuilder<\n+                RethFullAdapter<DB, N>,\n+                N::PoolBuilder,\n+                N::PayloadBuilder,\n+                N::NetworkBuilder,\n+            >,\n+            FullNodeComponentsAdapter<\n+                RethFullAdapter<DB, N>,\n+                <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+            >,\n+        >,\n+    >\n+    where\n+        N: Node<FullNodeTypesAdapter<N, DB, RethFullProviderType<DB, <N as NodeTypes>::Evm>>>,\n+        N::PoolBuilder: PoolBuilder<RethFullAdapter<DB, N>>,\n+        N::NetworkBuilder: crate::components::NetworkBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+        N::PayloadBuilder: crate::components::PayloadServiceBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+    {\n+        self.with_types(node.clone()).with_components(node.components())\n+    }\n+}\n+\n+impl<DB> WithLaunchContext<DB, InitState>\n+where\n+    DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,\n+{\n+    /// Launches a preconfigured [Node]\n+    ///\n+    /// This bootstraps the node internals, creates all the components with the given [Node] type\n+    /// and launches the node.\n+    ///\n+    /// Returns a [NodeHandle] that can be used to interact with the node.\n+    pub async fn launch_node<N>(\n+        self,\n+        node: N,\n+    ) -> eyre::Result<\n+        NodeHandle<\n+            FullNodeComponentsAdapter<\n+                RethFullAdapter<DB, N>,\n+                <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+            >,\n+        >,\n+    >\n+    where\n+        N: Node<FullNodeTypesAdapter<N, DB, RethFullProviderType<DB, <N as NodeTypes>::Evm>>>,\n+        N::PoolBuilder: PoolBuilder<RethFullAdapter<DB, N>>,\n+        N::NetworkBuilder: crate::components::NetworkBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+        N::PayloadBuilder: crate::components::PayloadServiceBuilder<\n+            RethFullAdapter<DB, N>,\n+            <N::PoolBuilder as PoolBuilder<RethFullAdapter<DB, N>>>::Pool,\n+        >,\n+    {\n+        self.node(node).launch().await\n+    }\n+}\n+\n+impl<DB, Types> WithLaunchContext<DB, TypesState<Types, DB>>\n+where\n+    Types: NodeTypes,\n+    DB: Database + Clone + Unpin + 'static,\n+{\n+    /// Configures the node's components.\n+    ///\n+    /// The given components builder is used to create the components of the node when it is\n+    /// launched.\n+    pub fn with_components<Components>(\n+        self,\n+        components_builder: Components,\n+    ) -> WithLaunchContext<\n+        DB,\n+        ComponentsState<\n+            Types,\n+            Components,\n+            FullNodeComponentsAdapter<\n+                FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                Components::Pool,\n+            >,\n+        >,\n+    >\n+    where\n+        Components: NodeComponentsBuilder<\n+            FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+        >,\n+    {\n+        WithLaunchContext {\n+            builder: self.builder.with_components(components_builder),\n+            task_executor: self.task_executor,\n+            data_dir: self.data_dir,\n+        }\n+    }\n+}\n+\n+impl<DB, Types, Components>\n+    WithLaunchContext<\n+        DB,\n+        ComponentsState<\n+            Types,\n+            Components,\n+            FullNodeComponentsAdapter<\n+                FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                Components::Pool,\n+            >,\n+        >,\n+    >\n+where\n+    DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,\n+    Types: NodeTypes,\n+    Components: NodeComponentsBuilder<\n+        FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+    >,\n+{\n+    /// Apply a function to the components builder.\n+    pub fn map_components(self, f: impl FnOnce(Components) -> Components) -> Self {\n+        Self {\n+            builder: self.builder.map_components(f),\n+            task_executor: self.task_executor,\n+            data_dir: self.data_dir,\n+        }\n+    }\n+\n+    /// Sets the hook that is run once the node's components are initialized.\n+    pub fn on_component_initialized<F>(mut self, hook: F) -> Self\n+    where\n+        F: Fn(\n+                FullNodeComponentsAdapter<\n+                    FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                    Components::Pool,\n+                >,\n+            ) -> eyre::Result<()>\n+            + Send\n+            + 'static,\n+    {\n+        self.builder.state.hooks.set_on_component_initialized(hook);\n+        self\n+    }\n+\n+    /// Sets the hook that is run once the node has started.\n+    pub fn on_node_started<F>(mut self, hook: F) -> Self\n+    where\n+        F: Fn(\n+                FullNode<\n+                    FullNodeComponentsAdapter<\n+                        FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                        Components::Pool,\n+                    >,\n+                >,\n+            ) -> eyre::Result<()>\n+            + Send\n+            + 'static,\n+    {\n+        self.builder.state.hooks.set_on_node_started(hook);\n+        self\n+    }\n+\n+    /// Sets the hook that is run once the rpc server is started.\n+    pub fn on_rpc_started<F>(mut self, hook: F) -> Self\n+    where\n+        F: Fn(\n+                RpcContext<\n+                    '_,\n+                    FullNodeComponentsAdapter<\n+                        FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                        Components::Pool,\n+                    >,\n+                >,\n+                RethRpcServerHandles,\n+            ) -> eyre::Result<()>\n+            + Send\n+            + 'static,\n+    {\n+        self.builder.state.rpc.set_on_rpc_started(hook);\n+        self\n+    }\n+\n+    /// Sets the hook that is run to configure the rpc modules.\n+    pub fn extend_rpc_modules<F>(mut self, hook: F) -> Self\n+    where\n+        F: Fn(\n+                RpcContext<\n+                    '_,\n+                    FullNodeComponentsAdapter<\n+                        FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                        Components::Pool,\n+                    >,\n+                >,\n+            ) -> eyre::Result<()>\n+            + Send\n+            + 'static,\n+    {\n+        self.builder.state.rpc.set_extend_rpc_modules(hook);\n+        self\n+    }\n+\n+    /// Launches the node and returns a handle to it.\n+    pub async fn launch(\n+        self,\n+    ) -> eyre::Result<\n+        NodeHandle<\n+            FullNodeComponentsAdapter<\n+                FullNodeTypesAdapter<Types, DB, RethFullProviderType<DB, Types::Evm>>,\n+                Components::Pool,\n+            >,\n+        >,\n+    > {\n+        let Self { builder, task_executor, data_dir } = self;\n+\n+        builder.launch(task_executor, data_dir).await\n+    }\n+\n+    /// Check that the builder can be launched\n+    ///\n+    /// This is useful when writing tests to ensure that the builder is configured correctly.\n+    pub fn check_launch(self) -> Self {\n+        self\n+    }\n+}\n+\n /// Captures the necessary context for building the components of the node.\n #[derive(Debug)]\n pub struct BuilderContext<Node: FullNodeTypes> {\n@@ -712,6 +1050,17 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {\n         self.config.builder.clone()\n     }\n \n+    /// Returns the default network config for the node.\n+    pub fn network_config(&self) -> eyre::Result<NetworkConfig<Node::Provider>> {\n+        self.config.network_config(\n+            &self.reth_config,\n+            self.provider.clone(),\n+            self.executor.clone(),\n+            self.head,\n+            self.data_dir(),\n+        )\n+    }\n+\n     /// Creates the [NetworkBuilder] for the node.\n     pub async fn network_builder(&self) -> eyre::Result<NetworkBuilder<Node::Provider, (), ()>> {\n         self.config\n@@ -725,11 +1074,8 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {\n             .await\n     }\n \n-    /// Creates the [NetworkBuilder] for the node and blocks until it is ready.\n-    pub fn network_builder_blocking(&self) -> eyre::Result<NetworkBuilder<Node::Provider, (), ()>> {\n-        self.executor.block_on(self.network_builder())\n-    }\n-\n+    /// Convenience function to start the network.\n+    ///\n     /// Spawns the configured network and associated tasks and returns the [NetworkHandle] connected\n     /// to that network.\n     pub fn start_network<Pool>(\n@@ -741,17 +1087,7 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {\n         Pool: TransactionPool + Unpin + 'static,\n     {\n         let (handle, network, txpool, eth) = builder\n-            .transactions(\n-                pool,\n-                TransactionsManagerConfig {\n-                    transaction_fetcher_config: TransactionFetcherConfig::new(\n-                        self.config.network.soft_limit_byte_size_pooled_transactions_response,\n-                        self.config\n-                            .network\n-                            .soft_limit_byte_size_pooled_transactions_response_on_pack_request,\n-                    ),\n-                },\n-            )\n+            .transactions(pool, Default::default())\n             .request_handler(self.provider().clone())\n             .split_with_handle();\n "},{"sha":"57e4d8639b085a29a9ce435957c03a88e7e18578","filename":"crates/node-builder/src/components/builder.rs","status":"modified","additions":13,"deletions":4,"changes":17,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fbuilder.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fbuilder.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fbuilder.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -87,6 +87,9 @@ where\n     Node: FullNodeTypes,\n {\n     /// Configures the pool builder.\n+    ///\n+    /// This accepts a [PoolBuilder] instance that will be used to create the node's transaction\n+    /// pool.\n     pub fn pool<PB>(self, pool_builder: PB) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB>\n     where\n         PB: PoolBuilder<Node>,\n@@ -102,6 +105,9 @@ where\n     PoolB: PoolBuilder<Node>,\n {\n     /// Configures the network builder.\n+    ///\n+    /// This accepts a [NetworkBuilder] instance that will be used to create the node's network\n+    /// stack.\n     pub fn network<NB>(self, network_builder: NB) -> ComponentsBuilder<Node, PoolB, PayloadB, NB>\n     where\n         NB: NetworkBuilder<Node, PoolB::Pool>,\n@@ -111,6 +117,9 @@ where\n     }\n \n     /// Configures the payload builder.\n+    ///\n+    /// This accepts a [PayloadServiceBuilder] instance that will be used to create the node's\n+    /// payload builder service.\n     pub fn payload<PB>(self, payload_builder: PB) -> ComponentsBuilder<Node, PoolB, PB, NetworkB>\n     where\n         PB: PayloadServiceBuilder<Node, PoolB::Pool>,\n@@ -130,15 +139,15 @@ where\n {\n     type Pool = PoolB::Pool;\n \n-    fn build_components(\n+    async fn build_components(\n         self,\n         context: &BuilderContext<Node>,\n     ) -> eyre::Result<NodeComponents<Node, Self::Pool>> {\n         let Self { pool_builder, payload_builder, network_builder, _marker } = self;\n \n-        let pool = pool_builder.build_pool(context)?;\n-        let network = network_builder.build_network(context, pool.clone())?;\n-        let payload_builder = payload_builder.spawn_payload_service(context, pool.clone())?;\n+        let pool = pool_builder.build_pool(context).await?;\n+        let network = network_builder.build_network(context, pool.clone()).await?;\n+        let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?;\n \n         Ok(NodeComponents { transaction_pool: pool, network, payload_builder })\n     }"},{"sha":"e6bda16c02feeab4127472006df23f8189ef7de9","filename":"crates/node-builder/src/components/network.rs","status":"modified","additions":15,"deletions":5,"changes":20,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fnetwork.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fnetwork.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fnetwork.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -3,20 +3,30 @@\n use crate::{node::FullNodeTypes, BuilderContext};\n use reth_network::NetworkHandle;\n use reth_transaction_pool::TransactionPool;\n+use std::future::Future;\n \n /// A type that knows how to build the network implementation.\n-pub trait NetworkBuilder<Node: FullNodeTypes, Pool: TransactionPool> {\n+pub trait NetworkBuilder<Node: FullNodeTypes, Pool: TransactionPool>: Send {\n     /// Launches the network implementation and returns the handle to it.\n-    fn build_network(self, ctx: &BuilderContext<Node>, pool: Pool) -> eyre::Result<NetworkHandle>;\n+    fn build_network(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> impl Future<Output = eyre::Result<NetworkHandle>> + Send;\n }\n \n-impl<Node, F, Pool> NetworkBuilder<Node, Pool> for F\n+impl<Node, F, Fut, Pool> NetworkBuilder<Node, Pool> for F\n where\n     Node: FullNodeTypes,\n     Pool: TransactionPool,\n-    F: FnOnce(&BuilderContext<Node>, Pool) -> eyre::Result<NetworkHandle>,\n+    F: Fn(&BuilderContext<Node>, Pool) -> Fut + Send,\n+    Fut: Future<Output = eyre::Result<NetworkHandle>> + Send,\n {\n-    fn build_network(self, ctx: &BuilderContext<Node>, pool: Pool) -> eyre::Result<NetworkHandle> {\n+    fn build_network(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> impl Future<Output = eyre::Result<NetworkHandle>> + Send {\n         self(ctx, pool)\n     }\n }"},{"sha":"4a92e4b8823dcdb62f0ec98e3151e12e1f7fa455","filename":"crates/node-builder/src/components/payload.rs","status":"modified","additions":9,"deletions":5,"changes":14,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpayload.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpayload.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpayload.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -3,28 +3,32 @@\n use crate::{node::FullNodeTypes, BuilderContext};\n use reth_payload_builder::PayloadBuilderHandle;\n use reth_transaction_pool::TransactionPool;\n+use std::future::Future;\n \n /// A type that knows how to spawn the payload service.\n-pub trait PayloadServiceBuilder<Node: FullNodeTypes, Pool: TransactionPool> {\n+pub trait PayloadServiceBuilder<Node: FullNodeTypes, Pool: TransactionPool>: Send {\n     /// Spawns the payload service and returns the handle to it.\n+    ///\n+    /// The [BuilderContext] is provided to allow give to access the node's configuration.\n     fn spawn_payload_service(\n         self,\n         ctx: &BuilderContext<Node>,\n         pool: Pool,\n-    ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>>;\n+    ) -> impl Future<Output = eyre::Result<PayloadBuilderHandle<Node::Engine>>> + Send;\n }\n \n-impl<Node, F, Pool> PayloadServiceBuilder<Node, Pool> for F\n+impl<Node, F, Fut, Pool> PayloadServiceBuilder<Node, Pool> for F\n where\n     Node: FullNodeTypes,\n     Pool: TransactionPool,\n-    F: FnOnce(&BuilderContext<Node>, Pool) -> eyre::Result<PayloadBuilderHandle<Node::Engine>>,\n+    F: Fn(&BuilderContext<Node>, Pool) -> Fut + Send,\n+    Fut: Future<Output = eyre::Result<PayloadBuilderHandle<Node::Engine>>> + Send,\n {\n     fn spawn_payload_service(\n         self,\n         ctx: &BuilderContext<Node>,\n         pool: Pool,\n-    ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> {\n+    ) -> impl Future<Output = eyre::Result<PayloadBuilderHandle<Node::Engine>>> + Send {\n         self(ctx, pool)\n     }\n }"},{"sha":"8a6bd62c81fa024c9b395e540661acd08a9654d1","filename":"crates/node-builder/src/components/pool.rs","status":"modified","additions":13,"deletions":5,"changes":18,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpool.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpool.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Fpool.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,25 +1,33 @@\n //! Pool component for the node builder.\n use crate::{node::FullNodeTypes, BuilderContext};\n use reth_transaction_pool::TransactionPool;\n+use std::future::Future;\n \n /// A type that knows how to build the transaction pool.\n-pub trait PoolBuilder<Node: FullNodeTypes> {\n+pub trait PoolBuilder<Node: FullNodeTypes>: Send {\n     /// The transaction pool to build.\n     type Pool: TransactionPool + Unpin + 'static;\n \n     /// Creates the transaction pool.\n-    fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool>;\n+    fn build_pool(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+    ) -> impl Future<Output = eyre::Result<Self::Pool>> + Send;\n }\n \n-impl<Node, F, Pool> PoolBuilder<Node> for F\n+impl<Node, F, Fut, Pool> PoolBuilder<Node> for F\n where\n     Node: FullNodeTypes,\n     Pool: TransactionPool + Unpin + 'static,\n-    F: FnOnce(&BuilderContext<Node>) -> eyre::Result<Pool>,\n+    F: FnOnce(&BuilderContext<Node>) -> Fut + Send,\n+    Fut: Future<Output = eyre::Result<Pool>> + Send,\n {\n     type Pool = Pool;\n \n-    fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n+    fn build_pool(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+    ) -> impl Future<Output = eyre::Result<Self::Pool>> {\n         self(ctx)\n     }\n }"},{"sha":"7aa946526793ee63589214e94da957c6dedd39fb","filename":"crates/node-builder/src/components/traits.rs","status":"modified","additions":6,"deletions":4,"changes":10,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Ftraits.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Ftraits.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fcomponents%2Ftraits.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -125,21 +125,23 @@ pub trait NodeComponentsBuilder<Node: FullNodeTypes> {\n     fn build_components(\n         self,\n         context: &BuilderContext<Node>,\n-    ) -> eyre::Result<NodeComponents<Node, Self::Pool>>;\n+    ) -> impl std::future::Future<Output = eyre::Result<NodeComponents<Node, Self::Pool>>> + Send;\n }\n \n-impl<Node, F, Pool> NodeComponentsBuilder<Node> for F\n+impl<Node, F, Fut, Pool> NodeComponentsBuilder<Node> for F\n where\n     Node: FullNodeTypes,\n-    F: FnOnce(&BuilderContext<Node>) -> eyre::Result<NodeComponents<Node, Pool>>,\n+    F: FnOnce(&BuilderContext<Node>) -> Fut + Send,\n+    Fut: std::future::Future<Output = eyre::Result<NodeComponents<Node, Pool>>> + Send,\n     Pool: TransactionPool + Unpin + 'static,\n {\n     type Pool = Pool;\n \n     fn build_components(\n         self,\n         ctx: &BuilderContext<Node>,\n-    ) -> eyre::Result<NodeComponents<Node, Pool>> {\n+    ) -> impl std::future::Future<Output = eyre::Result<NodeComponents<Node, Self::Pool>>> + Send\n+    {\n         self(ctx)\n     }\n }"},{"sha":"c5174632ece756714bb408cd11964da3db5500b4","filename":"crates/node-builder/src/handle.rs","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fhandle.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fhandle.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fhandle.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -3,6 +3,7 @@ use reth_node_core::exit::NodeExitFuture;\n use std::fmt;\n \n /// A Handle to the launched node.\n+#[must_use = \"Needs to await the node exit future\"]\n pub struct NodeHandle<Node: FullNodeComponents> {\n     /// All node components.\n     pub node: FullNode<Node>,"},{"sha":"4233e9c73f11477f1e00acace4548bea2ee4bdb1","filename":"crates/node-builder/src/hooks.rs","status":"modified","additions":4,"deletions":4,"changes":8,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fhooks.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fhooks.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fhooks.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -72,7 +72,7 @@ impl<Node: FullNodeComponents> fmt::Debug for NodeHooks<Node> {\n }\n \n /// A helper trait for the event hook that is run once the node is initialized.\n-pub trait OnComponentInitializedHook<Node> {\n+pub trait OnComponentInitializedHook<Node>: Send {\n     /// Consumes the event hook and runs it.\n     ///\n     /// If this returns an error, the node launch will be aborted.\n@@ -81,15 +81,15 @@ pub trait OnComponentInitializedHook<Node> {\n \n impl<Node, F> OnComponentInitializedHook<Node> for F\n where\n-    F: Fn(Node) -> eyre::Result<()>,\n+    F: Fn(Node) -> eyre::Result<()> + Send,\n {\n     fn on_event(&self, node: Node) -> eyre::Result<()> {\n         self(node)\n     }\n }\n \n /// A helper trait that is run once the node is started.\n-pub trait OnNodeStartedHook<Node: FullNodeComponents> {\n+pub trait OnNodeStartedHook<Node: FullNodeComponents>: Send {\n     /// Consumes the event hook and runs it.\n     ///\n     /// If this returns an error, the node launch will be aborted.\n@@ -99,7 +99,7 @@ pub trait OnNodeStartedHook<Node: FullNodeComponents> {\n impl<Node, F> OnNodeStartedHook<Node> for F\n where\n     Node: FullNodeComponents,\n-    F: Fn(FullNode<Node>) -> eyre::Result<()>,\n+    F: Fn(FullNode<Node>) -> eyre::Result<()> + Send,\n {\n     fn on_event(&self, node: FullNode<Node>) -> eyre::Result<()> {\n         self(node)"},{"sha":"39268f49129746af1d448656ee7c4e7950811106","filename":"crates/node-builder/src/lib.rs","status":"modified","additions":6,"deletions":4,"changes":10,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -13,22 +13,24 @@ pub mod hooks;\n \n /// Support for configuring the higher level node types.\n pub mod node;\n+pub use node::*;\n \n /// Support for configuring the components of a node.\n pub mod components;\n \n mod builder;\n+pub use builder::*;\n+\n mod handle;\n-pub mod rpc;\n+pub use handle::NodeHandle;\n \n pub mod provider;\n-\n-pub use builder::*;\n-pub use handle::NodeHandle;\n+pub mod rpc;\n \n /// Re-export the core configuration traits.\n pub use reth_node_core::cli::config::{\n     PayloadBuilderConfig, RethNetworkConfig, RethRpcConfig, RethTransactionPoolConfig,\n };\n \n+// re-export the core config for convenience\n pub use reth_node_core::node_config::NodeConfig;"},{"sha":"226dab0f4aacb85cb677286edd0b06f5ca20dc59","filename":"crates/node-builder/src/node.rs","status":"modified","additions":61,"deletions":14,"changes":75,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fnode.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Fnode.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Fnode.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,18 +1,38 @@\n use crate::{\n-    components::FullNodeComponents,\n+    components::{ComponentsBuilder, FullNodeComponents},\n+    provider::FullProvider,\n     rpc::{RethRpcServerHandles, RpcRegistry},\n };\n use reth_db::database::Database;\n use reth_network::NetworkHandle;\n use reth_node_api::{evm::ConfigureEvm, primitives::NodePrimitives, EngineTypes};\n use reth_node_core::{\n-    cli::components::FullProvider,\n     dirs::{ChainPath, DataDirPath},\n     node_config::NodeConfig,\n+    rpc::builder::{auth::AuthServerHandle, RpcServerHandle},\n };\n use reth_payload_builder::PayloadBuilderHandle;\n+use reth_primitives::ChainSpec;\n+use reth_provider::ChainSpecProvider;\n use reth_tasks::TaskExecutor;\n-use std::marker::PhantomData;\n+use std::{marker::PhantomData, sync::Arc};\n+\n+/// A [Node] is a [NodeTypes] that comes with preconfigured components.\n+///\n+/// This can be used to configure the builder with a preset of components.\n+pub trait Node<N>: NodeTypes + Clone {\n+    /// The type that builds the node's pool.\n+    type PoolBuilder;\n+    /// The type that builds the node's network.\n+    type NetworkBuilder;\n+    /// The type that builds the node's payload service.\n+    type PayloadBuilder;\n+\n+    /// Returns the [ComponentsBuilder] for the node.\n+    fn components(\n+        self,\n+    ) -> ComponentsBuilder<N, Self::PoolBuilder, Self::PayloadBuilder, Self::NetworkBuilder>;\n+}\n \n /// The type that configures stateless node types, the node's primitive types.\n pub trait NodeTypes: Send + Sync + 'static {\n@@ -76,20 +96,47 @@ where\n }\n \n /// The launched node with all components including RPC handlers.\n+///\n+/// This can be used to interact with the launched node.\n #[derive(Debug)]\n pub struct FullNode<Node: FullNodeComponents> {\n-    pub(crate) evm_config: Node::Evm,\n-    pub(crate) pool: Node::Pool,\n-    pub(crate) network: NetworkHandle,\n-    pub(crate) provider: Node::Provider,\n-    pub(crate) payload_builder: PayloadBuilderHandle<Node::Engine>,\n-    pub(crate) executor: TaskExecutor,\n-    pub(crate) rpc_server_handles: RethRpcServerHandles,\n-    pub(crate) rpc_registry: RpcRegistry<Node>,\n+    /// The evm configuration.\n+    pub evm_config: Node::Evm,\n+    /// The node's transaction pool.\n+    pub pool: Node::Pool,\n+    /// Handle to the node's network.\n+    pub network: NetworkHandle,\n+    /// Provider to interact with the node's database\n+    pub provider: Node::Provider,\n+    /// Handle to the node's payload builder service.\n+    pub payload_builder: PayloadBuilderHandle<Node::Engine>,\n+    /// Task executor for the node.\n+    pub task_executor: TaskExecutor,\n+    /// Handles to the node's rpc servers\n+    pub rpc_server_handles: RethRpcServerHandles,\n+    /// The configured rpc namespaces\n+    pub rpc_registry: RpcRegistry<Node>,\n     /// The initial node config.\n-    pub(crate) config: NodeConfig,\n+    pub config: NodeConfig,\n     /// The data dir of the node.\n-    pub(crate) data_dir: ChainPath<DataDirPath>,\n+    pub data_dir: ChainPath<DataDirPath>,\n+}\n+\n+impl<Node: FullNodeComponents> FullNode<Node> {\n+    /// Returns the [ChainSpec] of the node.\n+    pub fn chain_spec(&self) -> Arc<ChainSpec> {\n+        self.provider.chain_spec()\n+    }\n+\n+    /// Returns the [RpcServerHandle] to the started rpc server.\n+    pub fn rpc_server_handle(&self) -> &RpcServerHandle {\n+        &self.rpc_server_handles.rpc\n+    }\n+\n+    /// Returns the [AuthServerHandle] to the started authenticated engine API server.\n+    pub fn auth_server_handle(&self) -> &AuthServerHandle {\n+        &self.rpc_server_handles.auth\n+    }\n }\n \n impl<Node: FullNodeComponents> Clone for FullNode<Node> {\n@@ -100,7 +147,7 @@ impl<Node: FullNodeComponents> Clone for FullNode<Node> {\n             network: self.network.clone(),\n             provider: self.provider.clone(),\n             payload_builder: self.payload_builder.clone(),\n-            executor: self.executor.clone(),\n+            task_executor: self.task_executor.clone(),\n             rpc_server_handles: self.rpc_server_handles.clone(),\n             rpc_registry: self.rpc_registry.clone(),\n             config: self.config.clone(),"},{"sha":"d2d9e99bdb33b27ebef6e3e5dd4bc8dc872f447b","filename":"crates/node-builder/src/rpc.rs","status":"modified","additions":25,"deletions":4,"changes":29,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Frpc.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-builder%2Fsrc%2Frpc.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-builder%2Fsrc%2Frpc.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -14,6 +14,7 @@ use reth_node_core::{\n         },\n     },\n };\n+use reth_payload_builder::PayloadBuilderHandle;\n use reth_rpc::JwtSecret;\n use reth_tasks::TaskExecutor;\n use reth_tracing::tracing::{debug, info};\n@@ -94,7 +95,7 @@ impl<Node: FullNodeComponents> fmt::Debug for RpcHooks<Node> {\n }\n \n /// Event hook that is called once the rpc server is started.\n-pub trait OnRpcStarted<Node: FullNodeComponents> {\n+pub trait OnRpcStarted<Node: FullNodeComponents>: Send {\n     /// The hook that is called once the rpc server is started.\n     fn on_rpc_started(\n         &self,\n@@ -105,7 +106,7 @@ pub trait OnRpcStarted<Node: FullNodeComponents> {\n \n impl<Node, F> OnRpcStarted<Node> for F\n where\n-    F: Fn(RpcContext<'_, Node>, RethRpcServerHandles) -> eyre::Result<()>,\n+    F: Fn(RpcContext<'_, Node>, RethRpcServerHandles) -> eyre::Result<()> + Send,\n     Node: FullNodeComponents,\n {\n     fn on_rpc_started(\n@@ -124,14 +125,14 @@ impl<Node: FullNodeComponents> OnRpcStarted<Node> for () {\n }\n \n /// Event hook that is called when the rpc server is started.\n-pub trait ExtendRpcModules<Node: FullNodeComponents> {\n+pub trait ExtendRpcModules<Node: FullNodeComponents>: Send {\n     /// The hook that is called once the rpc server is started.\n     fn extend_rpc_modules(&self, ctx: RpcContext<'_, Node>) -> eyre::Result<()>;\n }\n \n impl<Node, F> ExtendRpcModules<Node> for F\n where\n-    F: Fn(RpcContext<'_, Node>) -> eyre::Result<()>,\n+    F: Fn(RpcContext<'_, Node>) -> eyre::Result<()> + Send,\n     Node: FullNodeComponents,\n {\n     fn extend_rpc_modules(&self, ctx: RpcContext<'_, Node>) -> eyre::Result<()> {\n@@ -223,6 +224,26 @@ impl<'a, Node: FullNodeComponents> RpcContext<'a, Node> {\n     pub fn node(&self) -> &Node {\n         &self.node\n     }\n+\n+    /// Returns the transaction pool instance.\n+    pub fn pool(&self) -> &Node::Pool {\n+        self.node.pool()\n+    }\n+\n+    /// Returns provider to interact with the node.\n+    pub fn provider(&self) -> &Node::Provider {\n+        self.node.provider()\n+    }\n+\n+    /// Returns the handle to the network\n+    pub fn network(&self) -> &NetworkHandle {\n+        self.node.network()\n+    }\n+\n+    /// Returns the handle to the payload builder service\n+    pub fn payload_builder(&self) -> &PayloadBuilderHandle<Node::Engine> {\n+        self.node.payload_builder()\n+    }\n }\n \n /// Launch the rpc servers."},{"sha":"14b63dd743f280d053068122370a6b263c12edaf","filename":"crates/node-core/src/args/mod.rs","status":"modified","additions":0,"deletions":6,"changes":6,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Fmod.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Fmod.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fargs%2Fmod.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -51,12 +51,6 @@ pub use dev_args::DevArgs;\n mod pruning_args;\n pub use pruning_args::PruningArgs;\n \n-/// RollupArgs for configuring the op-reth rollup\n-#[cfg(feature = \"optimism\")]\n-mod rollup_args;\n-#[cfg(feature = \"optimism\")]\n-pub use rollup_args::RollupArgs;\n-\n pub mod utils;\n \n pub mod types;"},{"sha":"9e6344b01d61d585c3f5c2b44481a0523ddc2b6d","filename":"crates/node-core/src/args/payload_builder_args.rs","status":"modified","additions":0,"deletions":19,"changes":19,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Fpayload_builder_args.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Fpayload_builder_args.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fargs%2Fpayload_builder_args.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -34,18 +34,6 @@ pub struct PayloadBuilderArgs {\n     /// Maximum number of tasks to spawn for building a payload.\n     #[arg(long = \"builder.max-tasks\", default_value = \"3\", value_parser = RangedU64ValueParser::<usize>::new().range(1..))]\n     pub max_payload_tasks: usize,\n-\n-    /// By default the pending block equals the latest block\n-    /// to save resources and not leak txs from the tx-pool,\n-    /// this flag enables computing of the pending block\n-    /// from the tx-pool instead.\n-    ///\n-    /// If `compute_pending_block` is not enabled, the payload builder\n-    /// will use the payload attributes from the latest block. Note\n-    /// that this flag is not yet functional.\n-    #[cfg(feature = \"optimism\")]\n-    #[arg(long = \"rollup.compute-pending-block\")]\n-    pub compute_pending_block: bool,\n }\n \n impl Default for PayloadBuilderArgs {\n@@ -56,8 +44,6 @@ impl Default for PayloadBuilderArgs {\n             interval: Duration::from_secs(1),\n             deadline: SLOT_DURATION,\n             max_payload_tasks: 3,\n-            #[cfg(feature = \"optimism\")]\n-            compute_pending_block: false,\n         }\n     }\n }\n@@ -82,11 +68,6 @@ impl PayloadBuilderConfig for PayloadBuilderArgs {\n     fn max_payload_tasks(&self) -> usize {\n         self.max_payload_tasks\n     }\n-\n-    #[cfg(feature = \"optimism\")]\n-    fn compute_pending_block(&self) -> bool {\n-        self.compute_pending_block\n-    }\n }\n \n #[derive(Clone, Debug, Default)]"},{"sha":"50db2fcd05971c13ddb1ce2ebad586e32616bc22","filename":"crates/node-core/src/args/rpc_server_args.rs","status":"modified","additions":5,"deletions":85,"changes":90,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Frpc_server_args.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fargs%2Frpc_server_args.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fargs%2Frpc_server_args.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,18 +5,13 @@ use crate::{\n         types::{MaxU32, ZeroAsNoneU64},\n         GasPriceOracleArgs, RpcStateCacheArgs,\n     },\n-    cli::{\n-        components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},\n-        config::RethRpcConfig,\n-        ext::RethNodeCommandConfig,\n-    },\n+    cli::config::RethRpcConfig,\n     utils::get_or_create_jwt_secret_from_path,\n };\n use clap::{\n     builder::{PossibleValue, RangedU64ValueParser, TypedValueParser},\n     Arg, Args, Command,\n };\n-use futures::TryFutureExt;\n use rand::Rng;\n use reth_network_api::{NetworkInfo, Peers};\n use reth_node_api::{ConfigureEvmEnv, EngineTypes};\n@@ -32,18 +27,18 @@ use reth_rpc_builder::{\n     auth::{AuthServerConfig, AuthServerHandle},\n     constants,\n     error::RpcError,\n-    EthConfig, IpcServerBuilder, RethRpcModule, RpcModuleBuilder, RpcModuleConfig,\n-    RpcModuleSelection, RpcServerConfig, RpcServerHandle, ServerBuilder, TransportRpcModuleConfig,\n+    EthConfig, IpcServerBuilder, RethRpcModule, RpcModuleConfig, RpcModuleSelection,\n+    RpcServerConfig, RpcServerHandle, ServerBuilder, TransportRpcModuleConfig,\n };\n-use reth_rpc_engine_api::{EngineApi, EngineApiServer};\n+use reth_rpc_engine_api::EngineApi;\n use reth_tasks::TaskSpawner;\n use reth_transaction_pool::TransactionPool;\n use std::{\n     ffi::OsStr,\n     net::{IpAddr, Ipv4Addr, SocketAddr},\n     path::PathBuf,\n };\n-use tracing::{debug, info};\n+use tracing::debug;\n \n /// Default max number of subscriptions per connection.\n pub(crate) const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024;\n@@ -268,81 +263,6 @@ impl RpcServerArgs {\n         self\n     }\n \n-    /// Configures and launches _all_ servers.\n-    ///\n-    /// Returns the handles for the launched regular RPC server(s) (if any) and the server handle\n-    /// for the auth server that handles the `engine_` API that's accessed by the consensus\n-    /// layer.\n-    pub async fn start_servers<Reth, Engine, Conf, EngineT>(\n-        &self,\n-        components: &Reth,\n-        engine_api: Engine,\n-        jwt_secret: JwtSecret,\n-        conf: &mut Conf,\n-    ) -> eyre::Result<RethRpcServerHandles>\n-    where\n-        EngineT: EngineTypes + 'static,\n-        Engine: EngineApiServer<EngineT>,\n-        Reth: RethNodeComponents,\n-        Conf: RethNodeCommandConfig,\n-    {\n-        let auth_config = self.auth_server_config(jwt_secret)?;\n-\n-        let module_config = self.transport_rpc_module_config();\n-        debug!(target: \"reth::cli\", http=?module_config.http(), ws=?module_config.ws(), \"Using RPC module config\");\n-\n-        let (mut modules, mut auth_module, mut registry) = RpcModuleBuilder::default()\n-            .with_provider(components.provider())\n-            .with_pool(components.pool())\n-            .with_network(components.network())\n-            .with_events(components.events())\n-            .with_executor(components.task_executor())\n-            .with_evm_config(components.evm_config())\n-            .build_with_auth_server(module_config, engine_api);\n-\n-        let rpc_components = RethRpcComponents {\n-            registry: &mut registry,\n-            modules: &mut modules,\n-            auth_module: &mut auth_module,\n-        };\n-        // apply configured customization\n-        conf.extend_rpc_modules(self, components, rpc_components)?;\n-\n-        let server_config = self.rpc_server_config();\n-        let launch_rpc = modules.clone().start_server(server_config).map_ok(|handle| {\n-            if let Some(url) = handle.ipc_endpoint() {\n-                info!(target: \"reth::cli\", url=%url, \"RPC IPC server started\");\n-            }\n-            if let Some(addr) = handle.http_local_addr() {\n-                info!(target: \"reth::cli\", url=%addr, \"RPC HTTP server started\");\n-            }\n-            if let Some(addr) = handle.ws_local_addr() {\n-                info!(target: \"reth::cli\", url=%addr, \"RPC WS server started\");\n-            }\n-            handle\n-        });\n-\n-        let launch_auth = auth_module.clone().start_server(auth_config).map_ok(|handle| {\n-            let addr = handle.local_addr();\n-            info!(target: \"reth::cli\", url=%addr, \"RPC auth server started\");\n-            handle\n-        });\n-\n-        // launch servers concurrently\n-        let (rpc, auth) = futures::future::try_join(launch_rpc, launch_auth).await?;\n-        let handles = RethRpcServerHandles { rpc, auth };\n-\n-        // call hook\n-        let rpc_components = RethRpcComponents {\n-            registry: &mut registry,\n-            modules: &mut modules,\n-            auth_module: &mut auth_module,\n-        };\n-        conf.on_rpc_server_started(self, components, rpc_components, handles.clone())?;\n-\n-        Ok(handles)\n-    }\n-\n     /// Convenience function for starting a rpc server with configs which extracted from cli args.\n     pub async fn start_rpc_server<Provider, Pool, Network, Tasks, Events, EvmConfig>(\n         &self,"},{"sha":"b4a0f168fd7f8da0c9cdf223f8958f0deaf4e856","filename":"crates/node-core/src/cli/components.rs","status":"removed","additions":0,"deletions":230,"changes":230,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fcomponents.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fcomponents.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fcli%2Fcomponents.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,230 +0,0 @@\n-//! Components that are used by the node command.\n-\n-use reth_db::database::Database;\n-use reth_network::{NetworkEvents, NetworkProtocols};\n-use reth_network_api::{NetworkInfo, Peers};\n-use reth_node_api::ConfigureEvmEnv;\n-use reth_primitives::ChainSpec;\n-use reth_provider::{\n-    AccountReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader,\n-    DatabaseProviderFactory, EvmEnvProvider, StateProviderFactory,\n-};\n-use reth_rpc_builder::{\n-    auth::{AuthRpcModule, AuthServerHandle},\n-    RethModuleRegistry, RpcServerHandle, TransportRpcModules,\n-};\n-use reth_tasks::TaskSpawner;\n-use reth_transaction_pool::TransactionPool;\n-use std::{marker::PhantomData, sync::Arc};\n-\n-/// Helper trait to unify all provider traits for simplicity.\n-pub trait FullProvider<DB: Database>:\n-    DatabaseProviderFactory<DB>\n-    + BlockReaderIdExt\n-    + AccountReader\n-    + StateProviderFactory\n-    + EvmEnvProvider\n-    + ChainSpecProvider\n-    + ChangeSetReader\n-    + CanonStateSubscriptions\n-    + Clone\n-    + Unpin\n-    + 'static\n-{\n-}\n-\n-impl<T, DB: Database> FullProvider<DB> for T where\n-    T: DatabaseProviderFactory<DB>\n-        + BlockReaderIdExt\n-        + AccountReader\n-        + StateProviderFactory\n-        + EvmEnvProvider\n-        + ChainSpecProvider\n-        + ChangeSetReader\n-        + CanonStateSubscriptions\n-        + Clone\n-        + Unpin\n-        + 'static\n-{\n-}\n-\n-/// The trait that is implemented for the Node command.\n-pub trait RethNodeComponents: Clone + Send + Sync + 'static {\n-    /// Underlying database type.\n-    type DB: Database + Clone + Unpin + 'static;\n-    /// The Provider type that is provided by the node itself\n-    type Provider: FullProvider<Self::DB>;\n-    /// The transaction pool type\n-    type Pool: TransactionPool + Clone + Unpin + 'static;\n-    /// The network type used to communicate with p2p.\n-    type Network: NetworkInfo + Peers + NetworkProtocols + NetworkEvents + Clone + Unpin + 'static;\n-    /// The events type used to create subscriptions.\n-    type Events: CanonStateSubscriptions + Clone + 'static;\n-    /// The type that is used to spawn tasks.\n-    type Tasks: TaskSpawner + Clone + Unpin + 'static;\n-    /// The type that defines how to configure the EVM before execution.\n-    type EvmConfig: ConfigureEvmEnv + 'static;\n-\n-    /// Returns the instance of the provider\n-    fn provider(&self) -> Self::Provider;\n-\n-    /// Returns the instance of the task executor.\n-    fn task_executor(&self) -> Self::Tasks;\n-\n-    /// Returns the instance of the transaction pool.\n-    fn pool(&self) -> Self::Pool;\n-\n-    /// Returns the instance of the network API.\n-    fn network(&self) -> Self::Network;\n-\n-    /// Returns the instance of the events subscription handler.\n-    fn events(&self) -> Self::Events;\n-\n-    /// Returns the instance of the EVM config.\n-    fn evm_config(&self) -> Self::EvmConfig;\n-\n-    /// Helper function to return the chain spec.\n-    fn chain_spec(&self) -> Arc<ChainSpec> {\n-        self.provider().chain_spec()\n-    }\n-}\n-\n-/// Helper container to encapsulate [RethModuleRegistry],[TransportRpcModules] and [AuthRpcModule].\n-///\n-/// This can be used to access installed modules, or create commonly used handlers like\n-/// [reth_rpc::EthApi], and ultimately merge additional rpc handler into the configured transport\n-/// modules [TransportRpcModules] as well as configured authenticated methods [AuthRpcModule].\n-#[derive(Debug)]\n-#[allow(clippy::type_complexity)]\n-pub struct RethRpcComponents<'a, Reth: RethNodeComponents> {\n-    /// A Helper type the holds instances of the configured modules.\n-    ///\n-    /// This provides easy access to rpc handlers, such as [RethModuleRegistry::eth_api].\n-    pub registry: &'a mut RethModuleRegistry<\n-        Reth::Provider,\n-        Reth::Pool,\n-        Reth::Network,\n-        Reth::Tasks,\n-        Reth::Events,\n-        Reth::EvmConfig,\n-    >,\n-    /// Holds installed modules per transport type.\n-    ///\n-    /// This can be used to merge additional modules into the configured transports (http, ipc,\n-    /// ws). See [TransportRpcModules::merge_configured]\n-    pub modules: &'a mut TransportRpcModules,\n-    /// Holds jwt authenticated rpc module.\n-    ///\n-    /// This can be used to merge additional modules into the configured authenticated methods\n-    pub auth_module: &'a mut AuthRpcModule,\n-}\n-\n-/// A Generic implementation of the RethNodeComponents trait.\n-///\n-/// Represents components required for the Reth node.\n-#[derive(Clone, Debug)]\n-pub struct RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig> {\n-    /// Represents underlying database type.\n-    __phantom: PhantomData<DB>,\n-    /// Represents the provider instance.\n-    pub provider: Provider,\n-    /// Represents the transaction pool instance.\n-    pub pool: Pool,\n-    /// Represents the network instance used for communication.\n-    pub network: Network,\n-    /// Represents the task executor instance.\n-    pub task_executor: Tasks,\n-    /// Represents the events subscription handler instance.\n-    pub events: Events,\n-    /// Represents the type that is used to configure the EVM before execution.\n-    pub evm_config: EvmConfig,\n-}\n-\n-impl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>\n-    RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>\n-{\n-    /// Create new instance of the node components.\n-    pub fn new(\n-        provider: Provider,\n-        pool: Pool,\n-        network: Network,\n-        task_executor: Tasks,\n-        events: Events,\n-        evm_config: EvmConfig,\n-    ) -> Self {\n-        Self {\n-            provider,\n-            pool,\n-            network,\n-            task_executor,\n-            events,\n-            evm_config,\n-            __phantom: std::marker::PhantomData,\n-        }\n-    }\n-}\n-\n-impl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig> RethNodeComponents\n-    for RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>\n-where\n-    DB: Database + Clone + Unpin + 'static,\n-    Provider: FullProvider<DB> + Clone + 'static,\n-    Tasks: TaskSpawner + Clone + Unpin + 'static,\n-    Pool: TransactionPool + Clone + Unpin + 'static,\n-    Network: NetworkInfo + Peers + NetworkProtocols + NetworkEvents + Clone + Unpin + 'static,\n-    Events: CanonStateSubscriptions + Clone + 'static,\n-    EvmConfig: ConfigureEvmEnv + 'static,\n-{\n-    type DB = DB;\n-    type Provider = Provider;\n-    type Pool = Pool;\n-    type Network = Network;\n-    type Events = Events;\n-    type Tasks = Tasks;\n-    type EvmConfig = EvmConfig;\n-\n-    fn provider(&self) -> Self::Provider {\n-        self.provider.clone()\n-    }\n-\n-    fn task_executor(&self) -> Self::Tasks {\n-        self.task_executor.clone()\n-    }\n-\n-    fn pool(&self) -> Self::Pool {\n-        self.pool.clone()\n-    }\n-\n-    fn network(&self) -> Self::Network {\n-        self.network.clone()\n-    }\n-\n-    fn events(&self) -> Self::Events {\n-        self.events.clone()\n-    }\n-\n-    fn evm_config(&self) -> Self::EvmConfig {\n-        self.evm_config.clone()\n-    }\n-}\n-\n-/// Contains the handles to the spawned RPC servers.\n-///\n-/// This can be used to access the endpoints of the servers.\n-///\n-/// # Example\n-///\n-/// ```rust\n-/// use reth_node_core::{cli::components::RethRpcServerHandles, rpc::api::EthApiClient};\n-/// # async fn t(handles: RethRpcServerHandles) {\n-/// let client = handles.rpc.http_client().expect(\"http server not started\");\n-/// let block_number = client.block_number().await.unwrap();\n-/// # }\n-/// ```\n-#[derive(Debug, Clone)]\n-pub struct RethRpcServerHandles {\n-    /// The regular RPC server handle.\n-    pub rpc: RpcServerHandle,\n-    /// The handle to the auth server (engine API)\n-    pub auth: AuthServerHandle,\n-}"},{"sha":"f879984c8712f9eb14450c355e90a132dd2af27a","filename":"crates/node-core/src/cli/config.rs","status":"modified","additions":0,"deletions":4,"changes":4,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fcli%2Fconfig.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fcli%2Fconfig.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fcli%2Fconfig.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -105,10 +105,6 @@ pub trait PayloadBuilderConfig {\n \n     /// Maximum number of tasks to spawn for building a payload.\n     fn max_payload_tasks(&self) -> usize;\n-\n-    /// Returns whether or not to construct the pending block.\n-    #[cfg(feature = \"optimism\")]\n-    fn compute_pending_block(&self) -> bool;\n }\n \n /// A trait that represents the configured network and can be used to apply additional configuration"},{"sha":"cc2e6fbbdf97e76aff91e3c6e8b7f939b94621dd","filename":"crates/node-core/src/cli/db_type.rs","status":"removed","additions":0,"deletions":125,"changes":125,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fdb_type.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fdb_type.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fcli%2Fdb_type.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,125 +0,0 @@\n-//! A real or test database type\n-\n-use crate::dirs::{ChainPath, DataDirPath, MaybePlatformPath};\n-use alloy_chains::Chain;\n-use reth_db::{\n-    init_db,\n-    mdbx::DatabaseArguments,\n-    test_utils::{create_test_rw_db, TempDatabase},\n-    DatabaseEnv,\n-};\n-use reth_interfaces::db::LogLevel;\n-use std::{str::FromStr, sync::Arc};\n-\n-/// A type that represents either a _real_ (represented by a path), or _test_ database, which will\n-/// use a [TempDatabase].\n-#[derive(Debug, Clone)]\n-pub enum DatabaseBuilder {\n-    /// The real database type, with a specified data dir\n-    Real(MaybePlatformPath<DataDirPath>),\n-    /// The test database type\n-    Test,\n-}\n-\n-impl DatabaseBuilder {\n-    /// Creates a _test_ database\n-    pub fn test() -> Self {\n-        Self::Test\n-    }\n-\n-    /// Initializes and returns the [DatabaseInstance] depending on the current database type.\n-    ///\n-    /// If the [DatabaseBuilder] is test, then the [ChainPath] constructed will be derived from the\n-    /// db path of the [TempDatabase] and the given chain. The [LogLevel] will not be used.\n-    ///\n-    /// If the [DatabaseBuilder] is real, then the db will be initialized using the given log level\n-    /// and the [ChainPath] will be derived from the given path and chain. This database path is\n-    /// then passed into [init_db].\n-    pub fn init_db(\n-        self,\n-        log_level: Option<LogLevel>,\n-        chain: Chain,\n-    ) -> eyre::Result<DatabaseInstance> {\n-        match self {\n-            DatabaseBuilder::Test => {\n-                let db = create_test_rw_db();\n-                let db_path_str = db.path().to_str().expect(\"Path is not valid unicode\");\n-                let path = MaybePlatformPath::<DataDirPath>::from_str(db_path_str)\n-                    .expect(\"Path is not valid\");\n-                let data_dir = path.unwrap_or_chain_default(chain);\n-\n-                Ok(DatabaseInstance::Test { db, data_dir })\n-            }\n-            DatabaseBuilder::Real(path) => {\n-                let data_dir = path.unwrap_or_chain_default(chain);\n-                let db_path = data_dir.db_path();\n-\n-                tracing::info!(target: \"reth::cli\", path = ?db_path, \"Opening database\");\n-                let db = Arc::new(\n-                    init_db(db_path.clone(), DatabaseArguments::default().log_level(log_level))?\n-                        .with_metrics(),\n-                );\n-                Ok(DatabaseInstance::Real { db, data_dir })\n-            }\n-        }\n-    }\n-}\n-\n-/// The [Default] implementation for [DatabaseBuilder] uses the _real_ variant, using the default\n-/// value for the inner [MaybePlatformPath].\n-impl Default for DatabaseBuilder {\n-    fn default() -> Self {\n-        Self::Real(MaybePlatformPath::<DataDirPath>::default())\n-    }\n-}\n-\n-/// A constructed database type, with a [ChainPath].\n-#[derive(Debug, Clone)]\n-pub enum DatabaseInstance {\n-    /// The test database\n-    Test {\n-        /// The database\n-        db: Arc<TempDatabase<DatabaseEnv>>,\n-        /// The data dir\n-        data_dir: ChainPath<DataDirPath>,\n-    },\n-    /// The real database\n-    Real {\n-        /// The database\n-        db: Arc<DatabaseEnv>,\n-        /// The data dir\n-        data_dir: ChainPath<DataDirPath>,\n-    },\n-}\n-\n-impl DatabaseInstance {\n-    /// Returns the data dir for this database instance\n-    pub fn data_dir(&self) -> &ChainPath<DataDirPath> {\n-        match self {\n-            Self::Test { data_dir, .. } => data_dir,\n-            Self::Real { data_dir, .. } => data_dir,\n-        }\n-    }\n-}\n-\n-#[cfg(test)]\n-mod tests {\n-    use super::*;\n-\n-    #[test]\n-    fn test_database_db_dir() {\n-        // create temp dir to test that the db path is correct\n-        let tempdir = tempfile::tempdir().unwrap();\n-        let expected_datadir_path = tempdir.path().to_path_buf();\n-        let expected_db_path = tempdir.path().join(\"db\");\n-        let datadir_path = MaybePlatformPath::<DataDirPath>::from(tempdir.path().to_path_buf());\n-        let db = DatabaseBuilder::Real(datadir_path);\n-        let db = db.init_db(None, Chain::mainnet()).unwrap();\n-\n-        // ensure that the datadir path is correct\n-        assert_eq!(db.data_dir().data_dir_path(), expected_datadir_path);\n-\n-        // ensure that the db path is correct\n-        assert_eq!(db.data_dir().db_path(), expected_db_path);\n-    }\n-}"},{"sha":"178e7ea873353ee6cdb690a2e6a30ab64a0ce8b2","filename":"crates/node-core/src/cli/ext.rs","status":"removed","additions":0,"deletions":360,"changes":360,"blob_url":"https://github.com/paradigmxyz/reth/blob/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fext.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/7d36206dfe4348158d51d6a23b7da2e6de03841c/crates%2Fnode-core%2Fsrc%2Fcli%2Fext.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fcli%2Fext.rs?ref=7d36206dfe4348158d51d6a23b7da2e6de03841c","patch":"@@ -1,360 +0,0 @@\n-//! Support for integrating customizations into the CLI.\n-\n-use crate::cli::{\n-    components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},\n-    config::{PayloadBuilderConfig, RethNetworkConfig, RethRpcConfig},\n-};\n-use clap::Args;\n-use reth_basic_payload_builder::{\n-    BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig, PayloadBuilder,\n-};\n-use reth_node_api::EngineTypes;\n-use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};\n-use reth_provider::CanonStateSubscriptions;\n-use reth_tasks::TaskSpawner;\n-use std::{fmt, marker::PhantomData};\n-\n-/// A trait that allows for extending parts of the CLI with additional functionality.\n-///\n-/// This is intended as a way to allow to _extend_ the node command. For example, to register\n-/// additional RPC namespaces.\n-pub trait RethCliExt {\n-    /// Provides additional configuration for the node CLI command.\n-    ///\n-    /// This supports additional CLI arguments that can be used to modify the node configuration.\n-    ///\n-    /// If no additional CLI arguments are required, the [NoArgs] wrapper type can be used.\n-    type Node: RethNodeCommandExt;\n-}\n-\n-/// The default CLI extension.\n-impl RethCliExt for () {\n-    type Node = DefaultRethNodeCommandConfig;\n-}\n-\n-/// A trait that allows for extending and customizing parts of the rethr node command.\n-///\n-/// The functions are invoked during the initialization of the node command in the following order:\n-///\n-/// 1. [configure_network](RethNodeCommandConfig::configure_network)\n-/// 2. [on_components_initialized](RethNodeCommandConfig::on_components_initialized)\n-/// 3. [spawn_payload_builder_service](RethNodeCommandConfig::spawn_payload_builder_service)\n-/// 4. [extend_rpc_modules](RethNodeCommandConfig::extend_rpc_modules)\n-/// 5. [on_rpc_server_started](RethNodeCommandConfig::on_rpc_server_started)\n-/// 6. [on_node_started](RethNodeCommandConfig::on_node_started)\n-pub trait RethNodeCommandConfig: fmt::Debug {\n-    /// Invoked with the network configuration before the network is configured.\n-    ///\n-    /// This allows additional configuration of the network before it is launched.\n-    fn configure_network<Conf, Reth>(\n-        &mut self,\n-        config: &mut Conf,\n-        components: &Reth,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethNetworkConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        let _ = config;\n-        let _ = components;\n-        Ok(())\n-    }\n-\n-    /// Event hook called once all components have been initialized.\n-    ///\n-    /// This is called as soon as the node components have been initialized.\n-    fn on_components_initialized<Reth: RethNodeComponents>(\n-        &mut self,\n-        components: &Reth,\n-    ) -> eyre::Result<()> {\n-        let _ = components;\n-        Ok(())\n-    }\n-\n-    /// Event hook called once the node has been launched.\n-    ///\n-    /// This is called last after the node has been launched.\n-    fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {\n-        let _ = components;\n-        Ok(())\n-    }\n-\n-    /// Event hook called once the rpc servers has been started.\n-    ///\n-    /// This is called after the rpc server has been started.\n-    fn on_rpc_server_started<Conf, Reth>(\n-        &mut self,\n-        config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-        handles: RethRpcServerHandles,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        let _ = config;\n-        let _ = components;\n-        let _ = rpc_components;\n-        let _ = handles;\n-        Ok(())\n-    }\n-\n-    /// Allows for registering additional RPC modules for the transports.\n-    ///\n-    /// This is expected to call the merge functions of [reth_rpc_builder::TransportRpcModules], for\n-    /// example [reth_rpc_builder::TransportRpcModules::merge_configured].\n-    ///\n-    /// This is called before the rpc server will be started [Self::on_rpc_server_started].\n-    fn extend_rpc_modules<Conf, Reth>(\n-        &mut self,\n-        config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        let _ = config;\n-        let _ = components;\n-        let _ = rpc_components;\n-        Ok(())\n-    }\n-\n-    /// Configures the [PayloadBuilderService] for the node, spawns it and returns the\n-    /// [PayloadBuilderHandle].\n-    ///\n-    /// By default this spawns a [BasicPayloadJobGenerator] with the default configuration\n-    /// [BasicPayloadJobGeneratorConfig].\n-    fn spawn_payload_builder_service<Conf, Reth, Builder, Engine>(\n-        &mut self,\n-        conf: &Conf,\n-        components: &Reth,\n-        payload_builder: Builder,\n-    ) -> eyre::Result<PayloadBuilderHandle<Engine>>\n-    where\n-        Conf: PayloadBuilderConfig,\n-        Reth: RethNodeComponents,\n-        Engine: EngineTypes + 'static,\n-        Builder: PayloadBuilder<\n-                Reth::Pool,\n-                Reth::Provider,\n-                Attributes = Engine::PayloadBuilderAttributes,\n-                BuiltPayload = Engine::BuiltPayload,\n-            > + Unpin\n-            + 'static,\n-    {\n-        let payload_job_config = BasicPayloadJobGeneratorConfig::default()\n-            .interval(conf.interval())\n-            .deadline(conf.deadline())\n-            .max_payload_tasks(conf.max_payload_tasks())\n-            .extradata(conf.extradata_rlp_bytes())\n-            .max_gas_limit(conf.max_gas_limit());\n-\n-        // no extradata for optimism\n-        #[cfg(feature = \"optimism\")]\n-        let payload_job_config = payload_job_config.extradata(Default::default());\n-\n-        let payload_generator = BasicPayloadJobGenerator::with_builder(\n-            components.provider(),\n-            components.pool(),\n-            components.task_executor(),\n-            payload_job_config,\n-            components.chain_spec(),\n-            payload_builder,\n-        );\n-        let (payload_service, payload_builder) = PayloadBuilderService::new(\n-            payload_generator,\n-            components.events().canonical_state_stream(),\n-        );\n-\n-        components\n-            .task_executor()\n-            .spawn_critical(\"payload builder service\", Box::pin(payload_service));\n-\n-        Ok(payload_builder)\n-    }\n-}\n-\n-/// A trait that allows for extending parts of the CLI with additional functionality.\n-pub trait RethNodeCommandExt: RethNodeCommandConfig + fmt::Debug + clap::Args {}\n-\n-// blanket impl for all types that implement the required traits.\n-impl<T> RethNodeCommandExt for T where T: RethNodeCommandConfig + fmt::Debug + clap::Args {}\n-\n-/// The default configuration for the reth node command.\n-///\n-/// This is a convenience type for [NoArgs<()>].\n-#[derive(Debug, Clone, Copy, Default, Args)]\n-#[non_exhaustive]\n-pub struct DefaultRethNodeCommandConfig;\n-\n-impl RethNodeCommandConfig for DefaultRethNodeCommandConfig {}\n-\n-impl RethNodeCommandConfig for () {}\n-\n-/// A helper type for [RethCliExt] extension that don't require any additional clap Arguments.\n-#[derive(Debug, Clone, Copy)]\n-pub struct NoArgsCliExt<Conf>(PhantomData<Conf>);\n-\n-impl<Conf: RethNodeCommandConfig> RethCliExt for NoArgsCliExt<Conf> {\n-    type Node = NoArgs<Conf>;\n-}\n-\n-/// A helper struct that allows for wrapping a [RethNodeCommandConfig] value without providing\n-/// additional CLI arguments.\n-///\n-/// Note: This type must be manually filled with a [RethNodeCommandConfig] manually before executing\n-/// the reth node command.\n-#[derive(Debug, Clone, Copy, Default, Args)]\n-pub struct NoArgs<T = ()> {\n-    #[arg(skip)]\n-    inner: Option<T>,\n-}\n-\n-impl<T> NoArgs<T> {\n-    /// Creates a new instance of the wrapper type.\n-    pub fn with(inner: T) -> Self {\n-        Self { inner: Some(inner) }\n-    }\n-\n-    /// Sets the inner value.\n-    pub fn set(&mut self, inner: T) {\n-        self.inner = Some(inner)\n-    }\n-\n-    /// Transforms the configured value.\n-    pub fn map<U>(self, inner: U) -> NoArgs<U> {\n-        NoArgs::with(inner)\n-    }\n-\n-    /// Returns the inner value if it exists.\n-    pub fn inner(&self) -> Option<&T> {\n-        self.inner.as_ref()\n-    }\n-\n-    /// Returns a mutable reference to the inner value if it exists.\n-    pub fn inner_mut(&mut self) -> Option<&mut T> {\n-        self.inner.as_mut()\n-    }\n-\n-    /// Consumes the wrapper and returns the inner value if it exists.\n-    pub fn into_inner(self) -> Option<T> {\n-        self.inner\n-    }\n-}\n-\n-impl<T: RethNodeCommandConfig> RethNodeCommandConfig for NoArgs<T> {\n-    fn configure_network<Conf, Reth>(\n-        &mut self,\n-        config: &mut Conf,\n-        components: &Reth,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethNetworkConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        if let Some(conf) = self.inner_mut() {\n-            conf.configure_network(config, components)\n-        } else {\n-            Ok(())\n-        }\n-    }\n-\n-    fn on_components_initialized<Reth: RethNodeComponents>(\n-        &mut self,\n-        components: &Reth,\n-    ) -> eyre::Result<()> {\n-        if let Some(conf) = self.inner_mut() {\n-            conf.on_components_initialized(components)\n-        } else {\n-            Ok(())\n-        }\n-    }\n-\n-    fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {\n-        if let Some(conf) = self.inner_mut() {\n-            conf.on_node_started(components)\n-        } else {\n-            Ok(())\n-        }\n-    }\n-\n-    fn on_rpc_server_started<Conf, Reth>(\n-        &mut self,\n-        config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-        handles: RethRpcServerHandles,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        if let Some(conf) = self.inner_mut() {\n-            conf.on_rpc_server_started(config, components, rpc_components, handles)\n-        } else {\n-            Ok(())\n-        }\n-    }\n-\n-    fn extend_rpc_modules<Conf, Reth>(\n-        &mut self,\n-        config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        if let Some(conf) = self.inner_mut() {\n-            conf.extend_rpc_modules(config, components, rpc_components)\n-        } else {\n-            Ok(())\n-        }\n-    }\n-\n-    fn spawn_payload_builder_service<Conf, Reth, Builder, Engine>(\n-        &mut self,\n-        conf: &Conf,\n-        components: &Reth,\n-        payload_builder: Builder,\n-    ) -> eyre::Result<PayloadBuilderHandle<Engine>>\n-    where\n-        Conf: PayloadBuilderConfig,\n-        Reth: RethNodeComponents,\n-        Engine: EngineTypes + 'static,\n-        Builder: PayloadBuilder<\n-                Reth::Pool,\n-                Reth::Provider,\n-                Attributes = Engine::PayloadBuilderAttributes,\n-                BuiltPayload = Engine::BuiltPayload,\n-            > + Unpin\n-            + 'static,\n-    {\n-        self.inner_mut()\n-            .ok_or_else(|| eyre::eyre!(\"config value must be set\"))?\n-            .spawn_payload_builder_service(conf, components, payload_builder)\n-    }\n-}\n-\n-impl<T> From<T> for NoArgs<T> {\n-    fn from(value: T) -> Self {\n-        Self::with(value)\n-    }\n-}\n-\n-#[cfg(test)]\n-mod tests {\n-    use super::*;\n-\n-    fn assert_ext<T: RethNodeCommandExt>() {}\n-\n-    #[test]\n-    fn ensure_ext() {\n-        assert_ext::<DefaultRethNodeCommandConfig>();\n-        assert_ext::<NoArgs<()>>();\n-    }\n-}"},{"sha":"fa14c5ee8ccc24acfe136e138fe04277844ba73e","filename":"crates/node-core/src/cli/mod.rs","status":"modified","additions":1,"deletions":4,"changes":5,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fcli%2Fmod.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fcli%2Fmod.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fcli%2Fmod.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,7 +1,4 @@\n-//! Types for the CLI.\n+//! Additional CLI configuration support.\n \n-pub mod components;\n pub mod config;\n-pub mod db_type;\n-pub mod ext;\n pub mod runner;"},{"sha":"35774d240c241acadb5490877b6c5d0a557595f5","filename":"crates/node-core/src/engine_api_store.rs","status":"renamed","additions":0,"deletions":0,"changes":0,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fengine_api_store.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fengine_api_store.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fengine_api_store.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","previous_filename":"bin/reth/src/commands/debug_cmd/engine_api_store.rs"},{"sha":"8295cc3d67a3d0220bdcab5673967ee11a492344","filename":"crates/node-core/src/lib.rs","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -10,6 +10,7 @@\n pub mod args;\n pub mod cli;\n pub mod dirs;\n+pub mod engine_api_store;\n pub mod events;\n pub mod exit;\n pub mod init;"},{"sha":"7eee5252f23e9efcbba14237b523536959a58d26","filename":"crates/node-core/src/node_config.rs","status":"modified","additions":26,"deletions":43,"changes":69,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fnode_config.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-core%2Fsrc%2Fnode_config.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-core%2Fsrc%2Fnode_config.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,8 +5,8 @@ use crate::{\n         get_secret_key, DatabaseArgs, DebugArgs, DevArgs, NetworkArgs, PayloadBuilderArgs,\n         PruningArgs, RpcServerArgs, TxPoolArgs,\n     },\n-    cli::{config::RethTransactionPoolConfig, db_type::DatabaseBuilder},\n-    dirs::{ChainPath, DataDirPath, MaybePlatformPath},\n+    cli::config::RethTransactionPoolConfig,\n+    dirs::{ChainPath, DataDirPath},\n     metrics::prometheus_exporter,\n     utils::{get_single_header, write_peers_to_file},\n };\n@@ -142,9 +142,6 @@ pub static PROMETHEUS_RECORDER_HANDLE: Lazy<PrometheusHandle> =\n /// ```\n #[derive(Debug, Clone)]\n pub struct NodeConfig {\n-    /// The test database\n-    pub database: DatabaseBuilder,\n-\n     /// The path to the configuration file to use.\n     pub config: Option<PathBuf>,\n \n@@ -199,17 +196,12 @@ pub struct NodeConfig {\n \n     /// All pruning related arguments\n     pub pruning: PruningArgs,\n-\n-    /// Rollup related arguments\n-    #[cfg(feature = \"optimism\")]\n-    pub rollup: crate::args::RollupArgs,\n }\n \n impl NodeConfig {\n     /// Creates a testing [NodeConfig], causing the database to be launched ephemerally.\n     pub fn test() -> Self {\n         let mut test = Self {\n-            database: DatabaseBuilder::test(),\n             config: None,\n             chain: MAINNET.clone(),\n             metrics: None,\n@@ -223,18 +215,16 @@ impl NodeConfig {\n             db: DatabaseArgs::default(),\n             dev: DevArgs::default(),\n             pruning: PruningArgs::default(),\n-            #[cfg(feature = \"optimism\")]\n-            rollup: crate::args::RollupArgs::default(),\n         };\n \n         // set all ports to zero by default for test instances\n         test = test.with_unused_ports();\n         test\n     }\n \n-    /// Set the datadir for the node\n-    pub fn with_datadir(mut self, datadir: MaybePlatformPath<DataDirPath>) -> Self {\n-        self.database = DatabaseBuilder::Real(datadir);\n+    /// Sets --dev mode for the node\n+    pub const fn dev(mut self) -> Self {\n+        self.dev.dev = true;\n         self\n     }\n \n@@ -316,13 +306,6 @@ impl NodeConfig {\n         self\n     }\n \n-    /// Set the rollup args for the node\n-    #[cfg(feature = \"optimism\")]\n-    pub fn with_rollup(mut self, rollup: crate::args::RollupArgs) -> Self {\n-        self.rollup = rollup;\n-        self\n-    }\n-\n     /// Get the network secret from the given data dir\n     pub fn network_secret(&self, data_dir: &ChainPath<DataDirPath>) -> eyre::Result<SecretKey> {\n         let network_secret_path =\n@@ -392,32 +375,43 @@ impl NodeConfig {\n         }\n     }\n \n-    /// Create the [NetworkBuilder].\n-    ///\n-    /// This only configures it and does not spawn it.\n-    pub async fn build_network<C>(\n+    /// Create the [NetworkConfig] for the node\n+    pub fn network_config<C>(\n         &self,\n         config: &Config,\n         client: C,\n         executor: TaskExecutor,\n         head: Head,\n         data_dir: &ChainPath<DataDirPath>,\n-    ) -> eyre::Result<NetworkBuilder<C, (), ()>>\n-    where\n-        C: BlockNumReader,\n-    {\n+    ) -> eyre::Result<NetworkConfig<C>> {\n         info!(target: \"reth::cli\", \"Connecting to P2P network\");\n         let secret_key = self.network_secret(data_dir)?;\n         let default_peers_path = data_dir.known_peers_path();\n-        let network_config = self.load_network_config(\n+        Ok(self.load_network_config(\n             config,\n             client,\n             executor.clone(),\n             head,\n             secret_key,\n             default_peers_path.clone(),\n-        );\n+        ))\n+    }\n \n+    /// Create the [NetworkBuilder].\n+    ///\n+    /// This only configures it and does not spawn it.\n+    pub async fn build_network<C>(\n+        &self,\n+        config: &Config,\n+        client: C,\n+        executor: TaskExecutor,\n+        head: Head,\n+        data_dir: &ChainPath<DataDirPath>,\n+    ) -> eyre::Result<NetworkBuilder<C, (), ()>>\n+    where\n+        C: BlockNumReader,\n+    {\n+        let network_config = self.network_config(config, client, executor, head, data_dir)?;\n         let builder = NetworkManager::builder(network_config).await?;\n         Ok(builder)\n     }\n@@ -773,14 +767,6 @@ impl NodeConfig {\n                 self.network.port + self.instance - 1,\n             )));\n \n-        // When `sequencer_endpoint` is configured, the node will forward all transactions to a\n-        // Sequencer node for execution and inclusion on L1, and disable its own txpool\n-        // gossip to prevent other parties in the network from learning about them.\n-        #[cfg(feature = \"optimism\")]\n-        let cfg_builder = cfg_builder\n-            .sequencer_endpoint(self.rollup.sequencer_http.clone())\n-            .disable_tx_gossip(self.rollup.disable_txpool_gossip);\n-\n         cfg_builder.build(client)\n     }\n \n@@ -914,7 +900,6 @@ impl NodeConfig {\n impl Default for NodeConfig {\n     fn default() -> Self {\n         Self {\n-            database: DatabaseBuilder::default(),\n             config: None,\n             chain: MAINNET.clone(),\n             metrics: None,\n@@ -928,8 +913,6 @@ impl Default for NodeConfig {\n             db: DatabaseArgs::default(),\n             dev: DevArgs::default(),\n             pruning: PruningArgs::default(),\n-            #[cfg(feature = \"optimism\")]\n-            rollup: crate::args::RollupArgs::default(),\n         }\n     }\n }"},{"sha":"6a8e7246b4afe01002c8fa82f136f7f03330dc1f","filename":"crates/node-ethereum/Cargo.toml","status":"modified","additions":4,"deletions":6,"changes":10,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-ethereum%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -25,14 +25,12 @@ reth-transaction-pool.workspace = true\n reth-network.workspace = true\n revm.workspace = true\n \n+# async\n+async-trait.workspace = true\n+\n # misc\n eyre.workspace = true\n serde.workspace = true\n \n [dev-dependencies]\n-reth-db.workspace = true\n-\n-[features]\n-# This is a workaround for reth-cli crate to allow this as mandatory dependency without breaking the build even if unused.\n-# This makes managing features and testing workspace easier because clippy always builds all members if --workspace is provided\n-optimism = []\n\\ No newline at end of file\n+reth-db.workspace = true\n\\ No newline at end of file"},{"sha":"641ed37fb5f8fa3a0172bc3a994bfc605e5309a3","filename":"crates/node-ethereum/src/lib.rs","status":"modified","additions":1,"deletions":2,"changes":3,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-ethereum%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -16,6 +16,5 @@ pub use engine::EthEngineTypes;\n /// [ConfigureEvmEnv](reth_node_api::ConfigureEvmEnv) trait.\n pub mod evm;\n pub use evm::EthEvmConfig;\n-\n-#[cfg(not(feature = \"optimism\"))]\n pub mod node;\n+pub use node::EthereumNode;"},{"sha":"0b988d59294d5cb43729f517289b782e3aea4caa","filename":"crates/node-ethereum/src/node.rs","status":"modified","additions":33,"deletions":11,"changes":44,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Fsrc%2Fnode.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Fsrc%2Fnode.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-ethereum%2Fsrc%2Fnode.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,7 +5,7 @@ use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGenera\n use reth_network::NetworkHandle;\n use reth_node_builder::{\n     components::{ComponentsBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder},\n-    node::{FullNodeTypes, NodeTypes},\n+    node::{FullNodeTypes, Node, NodeTypes},\n     BuilderContext, PayloadBuilderConfig,\n };\n use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};\n@@ -20,20 +20,19 @@ use reth_transaction_pool::{\n #[derive(Debug, Default, Clone, Copy)]\n #[non_exhaustive]\n pub struct EthereumNode;\n-// TODO make this stateful with evm config\n \n impl EthereumNode {\n     /// Returns a [ComponentsBuilder] configured for a regular Ethereum node.\n     pub fn components<Node>(\n-    ) -> ComponentsBuilder<Node, EthereumPoolBuilder, EthereumPayloadBuilder, EthereumNetwork>\n+    ) -> ComponentsBuilder<Node, EthereumPoolBuilder, EthereumPayloadBuilder, EthereumNetworkBuilder>\n     where\n         Node: FullNodeTypes<Engine = EthEngineTypes>,\n     {\n         ComponentsBuilder::default()\n             .node_types::<Node>()\n             .pool(EthereumPoolBuilder::default())\n             .payload(EthereumPayloadBuilder::default())\n-            .network(EthereumNetwork::default())\n+            .network(EthereumNetworkBuilder::default())\n     }\n }\n \n@@ -43,7 +42,26 @@ impl NodeTypes for EthereumNode {\n     type Evm = EthEvmConfig;\n \n     fn evm_config(&self) -> Self::Evm {\n-        todo!()\n+        EthEvmConfig::default()\n+    }\n+}\n+\n+impl<N> Node<N> for EthereumNode\n+where\n+    N: FullNodeTypes<Engine = EthEngineTypes>,\n+{\n+    type PoolBuilder = EthereumPoolBuilder;\n+    type NetworkBuilder = EthereumNetworkBuilder;\n+    type PayloadBuilder = EthereumPayloadBuilder;\n+\n+    fn components(\n+        self,\n+    ) -> ComponentsBuilder<N, Self::PoolBuilder, Self::PayloadBuilder, Self::NetworkBuilder> {\n+        ComponentsBuilder::default()\n+            .node_types::<N>()\n+            .pool(EthereumPoolBuilder::default())\n+            .payload(EthereumPayloadBuilder::default())\n+            .network(EthereumNetworkBuilder::default())\n     }\n }\n \n@@ -63,7 +81,7 @@ where\n {\n     type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore>;\n \n-    fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n+    async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n         let data_dir = ctx.data_dir();\n         let blob_store = DiskFileBlobStore::open(data_dir.blobstore_path(), Default::default())?;\n         let validator = TransactionValidationTaskExecutor::eth_builder(ctx.chain_spec())\n@@ -128,7 +146,7 @@ where\n     Node: FullNodeTypes<Engine = EthEngineTypes>,\n     Pool: TransactionPool + Unpin + 'static,\n {\n-    fn spawn_payload_service(\n+    async fn spawn_payload_service(\n         self,\n         ctx: &BuilderContext<Node>,\n         pool: Pool,\n@@ -162,17 +180,21 @@ where\n \n /// A basic ethereum payload service.\n #[derive(Debug, Default, Clone, Copy)]\n-pub struct EthereumNetwork {\n+pub struct EthereumNetworkBuilder {\n     // TODO add closure to modify network\n }\n \n-impl<Node, Pool> NetworkBuilder<Node, Pool> for EthereumNetwork\n+impl<Node, Pool> NetworkBuilder<Node, Pool> for EthereumNetworkBuilder\n where\n     Node: FullNodeTypes,\n     Pool: TransactionPool + Unpin + 'static,\n {\n-    fn build_network(self, ctx: &BuilderContext<Node>, pool: Pool) -> eyre::Result<NetworkHandle> {\n-        let network = ctx.network_builder_blocking()?;\n+    async fn build_network(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> eyre::Result<NetworkHandle> {\n+        let network = ctx.network_builder().await?;\n         let handle = ctx.start_network(network, pool);\n \n         Ok(handle)"},{"sha":"34ac15ef9f09c0d4dd6f4dbd61e81385c9fae661","filename":"crates/node-ethereum/tests/it/main.rs","status":"modified","additions":0,"deletions":1,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Ftests%2Fit%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-ethereum%2Ftests%2Fit%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-ethereum%2Ftests%2Fit%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,4 +1,3 @@\n-#[cfg(not(feature = \"optimism\"))]\n mod builder;\n \n fn main() {}"},{"sha":"b5fd7a088fd0595a985359df55d4b76434bb7f14","filename":"crates/node-optimism/Cargo.toml","status":"modified","additions":2,"deletions":1,"changes":3,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-optimism%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -27,7 +27,8 @@ reth-transaction-pool.workspace = true\n reth-network.workspace = true\n revm.workspace = true\n \n-# io\n+# misc\n+clap.workspace = true\n serde.workspace = true\n eyre.workspace = true\n "},{"sha":"8a3dddc810a438c6ba0b79038ca5157def57a849","filename":"crates/node-optimism/src/args.rs","status":"renamed","additions":14,"deletions":1,"changes":15,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Fargs.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Fargs.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-optimism%2Fsrc%2Fargs.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,4 +1,6 @@\n-//! clap [Args](clap::Args) for op-reth rollup configuration\n+//! Additional Node command arguments.\n+\n+//! clap [Args](clap::Args) for optimism rollup configuration\n \n /// Parameters for rollup configuration\n #[derive(Debug, Clone, Default, PartialEq, Eq, clap::Args)]\n@@ -16,6 +18,17 @@ pub struct RollupArgs {\n     /// prior to beginning normal syncing.\n     #[arg(long = \"rollup.enable-genesis-walkback\")]\n     pub enable_genesis_walkback: bool,\n+\n+    /// By default the pending block equals the latest block\n+    /// to save resources and not leak txs from the tx-pool,\n+    /// this flag enables computing of the pending block\n+    /// from the tx-pool instead.\n+    ///\n+    /// If `compute_pending_block` is not enabled, the payload builder\n+    /// will use the payload attributes from the latest block. Note\n+    /// that this flag is not yet functional.\n+    #[arg(long = \"rollup.compute-pending-block\")]\n+    pub compute_pending_block: bool,\n }\n \n #[cfg(test)]","previous_filename":"crates/node-core/src/args/rollup_args.rs"},{"sha":"9525f757b1421337a79594fa2b0e1da907a4f7c8","filename":"crates/node-optimism/src/lib.rs","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-optimism%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -19,5 +19,6 @@ pub use engine::OptimismEngineTypes;\n pub mod evm;\n pub use evm::OptimismEvmConfig;\n \n+pub mod args;\n pub mod node;\n pub use node::OptimismNode;"},{"sha":"545c88276a83d8b4e42411589b6434c614638c87","filename":"crates/node-optimism/src/node.rs","status":"modified","additions":87,"deletions":27,"changes":114,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Fnode.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Fsrc%2Fnode.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-optimism%2Fsrc%2Fnode.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,12 +1,12 @@\n //! Optimism Node types config.\n \n-use crate::{OptimismEngineTypes, OptimismEvmConfig};\n+use crate::{args::RollupArgs, OptimismEngineTypes, OptimismEvmConfig};\n use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};\n-use reth_network::NetworkHandle;\n+use reth_network::{NetworkHandle, NetworkManager};\n use reth_node_builder::{\n     components::{ComponentsBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder},\n     node::{FullNodeTypes, NodeTypes},\n-    BuilderContext, PayloadBuilderConfig,\n+    BuilderContext, Node, PayloadBuilderConfig,\n };\n use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};\n use reth_provider::CanonStateSubscriptions;\n@@ -17,23 +17,48 @@ use reth_transaction_pool::{\n };\n \n /// Type configuration for a regular Optimism node.\n-#[derive(Debug, Default, Clone, Copy)]\n+#[derive(Debug, Default, Clone)]\n #[non_exhaustive]\n-pub struct OptimismNode;\n-// TODO make this stateful with evm config\n+pub struct OptimismNode {\n+    /// Additional Optimism args\n+    pub args: RollupArgs,\n+}\n \n impl OptimismNode {\n-    /// Returns a [`ComponentsBuilder`] configured for a regular Ethereum node.\n+    /// Creates a new instance of the Optimism node type.\n+    pub const fn new(args: RollupArgs) -> Self {\n+        Self { args }\n+    }\n+\n+    /// Returns the components for the given [RollupArgs].\n     pub fn components<Node>(\n-    ) -> ComponentsBuilder<Node, OptimismPoolBuilder, OptimismPayloadBuilder, OptimismNetwork>\n+        args: RollupArgs,\n+    ) -> ComponentsBuilder<Node, OptimismPoolBuilder, OptimismPayloadBuilder, OptimismNetworkBuilder>\n     where\n         Node: FullNodeTypes<Engine = OptimismEngineTypes>,\n     {\n+        let RollupArgs { sequencer_http, disable_txpool_gossip, compute_pending_block, .. } = args;\n         ComponentsBuilder::default()\n             .node_types::<Node>()\n             .pool(OptimismPoolBuilder::default())\n-            .payload(OptimismPayloadBuilder::default())\n-            .network(OptimismNetwork)\n+            .payload(OptimismPayloadBuilder::new(compute_pending_block))\n+            .network(OptimismNetworkBuilder { sequencer_http, disable_txpool_gossip })\n+    }\n+}\n+\n+impl<N> Node<N> for OptimismNode\n+where\n+    N: FullNodeTypes<Engine = OptimismEngineTypes>,\n+{\n+    type PoolBuilder = OptimismPoolBuilder;\n+    type NetworkBuilder = OptimismNetworkBuilder;\n+    type PayloadBuilder = OptimismPayloadBuilder;\n+\n+    fn components(\n+        self,\n+    ) -> ComponentsBuilder<N, Self::PoolBuilder, Self::PayloadBuilder, Self::NetworkBuilder> {\n+        let Self { args } = self;\n+        Self::components(args)\n     }\n }\n \n@@ -43,7 +68,7 @@ impl NodeTypes for OptimismNode {\n     type Evm = OptimismEvmConfig;\n \n     fn evm_config(&self) -> Self::Evm {\n-        todo!()\n+        OptimismEvmConfig::default()\n     }\n }\n \n@@ -53,17 +78,15 @@ impl NodeTypes for OptimismNode {\n /// config.\n #[derive(Debug, Default, Clone, Copy)]\n #[non_exhaustive]\n-pub struct OptimismPoolBuilder {\n-    // TODO add options for txpool args\n-}\n+pub struct OptimismPoolBuilder;\n \n impl<Node> PoolBuilder<Node> for OptimismPoolBuilder\n where\n     Node: FullNodeTypes,\n {\n     type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore>;\n \n-    fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n+    async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n         let data_dir = ctx.data_dir();\n         let blob_store = DiskFileBlobStore::open(data_dir.blobstore_path(), Default::default())?;\n         let validator = TransactionValidationTaskExecutor::eth_builder(ctx.chain_spec())\n@@ -118,29 +141,47 @@ where\n     }\n }\n \n-/// A basic optimism payload service.\n+/// A basic optimism payload service builder\n #[derive(Debug, Default, Clone)]\n-#[non_exhaustive]\n-pub struct OptimismPayloadBuilder;\n+pub struct OptimismPayloadBuilder {\n+    /// By default the pending block equals the latest block\n+    /// to save resources and not leak txs from the tx-pool,\n+    /// this flag enables computing of the pending block\n+    /// from the tx-pool instead.\n+    ///\n+    /// If `compute_pending_block` is not enabled, the payload builder\n+    /// will use the payload attributes from the latest block. Note\n+    /// that this flag is not yet functional.\n+    pub compute_pending_block: bool,\n+}\n+\n+impl OptimismPayloadBuilder {\n+    /// Create a new instance with the given `compute_pending_block` flag.\n+    pub const fn new(compute_pending_block: bool) -> Self {\n+        Self { compute_pending_block }\n+    }\n+}\n \n impl<Node, Pool> PayloadServiceBuilder<Node, Pool> for OptimismPayloadBuilder\n where\n     Node: FullNodeTypes<Engine = OptimismEngineTypes>,\n     Pool: TransactionPool + Unpin + 'static,\n {\n-    fn spawn_payload_service(\n+    async fn spawn_payload_service(\n         self,\n         ctx: &BuilderContext<Node>,\n         pool: Pool,\n     ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> {\n-        let payload_builder = reth_optimism_payload_builder::OptimismPayloadBuilder::default();\n+        let payload_builder = reth_optimism_payload_builder::OptimismPayloadBuilder::default()\n+            .set_compute_pending_block(self.compute_pending_block);\n         let conf = ctx.payload_builder_config();\n \n         let payload_job_config = BasicPayloadJobGeneratorConfig::default()\n             .interval(conf.interval())\n             .deadline(conf.deadline())\n             .max_payload_tasks(conf.max_payload_tasks())\n-            .extradata(conf.extradata_rlp_bytes())\n+            // no extradata for OP\n+            .extradata(Default::default())\n             .max_gas_limit(conf.max_gas_limit());\n \n         let payload_generator = BasicPayloadJobGenerator::with_builder(\n@@ -160,17 +201,36 @@ where\n     }\n }\n \n-/// A basic ethereum payload service.\n-#[derive(Debug, Default, Clone, Copy)]\n-pub struct OptimismNetwork;\n+/// A basic optimism network builder.\n+#[derive(Debug, Default, Clone)]\n+pub struct OptimismNetworkBuilder {\n+    /// HTTP endpoint for the sequencer mempool\n+    pub sequencer_http: Option<String>,\n+    /// Disable transaction pool gossip\n+    pub disable_txpool_gossip: bool,\n+}\n \n-impl<Node, Pool> NetworkBuilder<Node, Pool> for OptimismNetwork\n+impl<Node, Pool> NetworkBuilder<Node, Pool> for OptimismNetworkBuilder\n where\n     Node: FullNodeTypes,\n     Pool: TransactionPool + Unpin + 'static,\n {\n-    fn build_network(self, ctx: &BuilderContext<Node>, pool: Pool) -> eyre::Result<NetworkHandle> {\n-        let network = ctx.network_builder_blocking()?;\n+    async fn build_network(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> eyre::Result<NetworkHandle> {\n+        let Self { sequencer_http, disable_txpool_gossip } = self;\n+        let mut network_config = ctx.network_config()?;\n+\n+        // When `sequencer_endpoint` is configured, the node will forward all transactions to a\n+        // Sequencer node for execution and inclusion on L1, and disable its own txpool\n+        // gossip to prevent other parties in the network from learning about them.\n+        network_config.tx_gossip_disabled = disable_txpool_gossip;\n+        network_config.optimism_network_config.sequencer_endpoint = sequencer_http;\n+\n+        let network = NetworkManager::builder(network_config).await?;\n+\n         let handle = ctx.start_network(network, pool);\n \n         Ok(handle)"},{"sha":"01bed6b9e17e27d354568f7a1ae043a7050fa14c","filename":"crates/node-optimism/tests/it/builder.rs","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Ftests%2Fit%2Fbuilder.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fnode-optimism%2Ftests%2Fit%2Fbuilder.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fnode-optimism%2Ftests%2Fit%2Fbuilder.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -12,7 +12,7 @@ fn test_basic_setup() {\n     let _builder = NodeBuilder::new(config)\n         .with_database(db)\n         .with_types(OptimismNode::default())\n-        .with_components(OptimismNode::components())\n+        .with_components(OptimismNode::components(Default::default()))\n         .on_component_initialized(move |ctx| {\n             let _provider = ctx.provider();\n             Ok(())"},{"sha":"6598023d7d391ff3c7d975fe03f419732df7fb0a","filename":"crates/payload/ethereum/Cargo.toml","status":"modified","additions":1,"deletions":6,"changes":7,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Fethereum%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Fethereum%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fpayload%2Fethereum%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -24,9 +24,4 @@ reth-basic-payload-builder.workspace = true\n revm.workspace = true\n \n # misc\n-tracing.workspace = true\n-\n-[features]\n-# This is a workaround for reth-cli crate to allow this as mandatory dependency without breaking the build even if unused.\n-# This makes managing features and testing workspace easier because clippy always builds all members if --workspace is provided\n-optimism = []\n+tracing.workspace = true\n\\ No newline at end of file"},{"sha":"37db8246fe71824831bb4344ce94877290237b78","filename":"crates/payload/ethereum/src/lib.rs","status":"modified","additions":342,"deletions":351,"changes":693,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Fethereum%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Fethereum%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fpayload%2Fethereum%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -7,90 +7,84 @@\n )]\n #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]\n \n-#[cfg(not(feature = \"optimism\"))]\n-pub use builder::*;\n-\n-#[cfg(not(feature = \"optimism\"))]\n-mod builder {\n-    use reth_basic_payload_builder::{\n-        commit_withdrawals, is_better_payload, pre_block_beacon_root_contract_call, BuildArguments,\n-        BuildOutcome, PayloadBuilder, PayloadConfig, WithdrawalsOutcome,\n-    };\n-    use reth_payload_builder::{\n-        error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes,\n-    };\n-    use reth_primitives::{\n-        constants::{\n-            eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE, EMPTY_RECEIPTS, EMPTY_TRANSACTIONS,\n-        },\n-        eip4844::calculate_excess_blob_gas,\n-        proofs,\n-        revm::env::tx_env_with_recovered,\n-        Block, Header, IntoRecoveredTransaction, Receipt, Receipts, EMPTY_OMMER_ROOT_HASH, U256,\n-    };\n-    use reth_provider::{BundleStateWithReceipts, StateProviderFactory};\n-    use reth_revm::database::StateProviderDatabase;\n-    use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool};\n-    use revm::{\n-        db::states::bundle_state::BundleRetention,\n-        primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},\n-        DatabaseCommit, State,\n-    };\n-    use tracing::{debug, trace, warn};\n-\n-    /// Ethereum payload builder\n-    #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]\n-    #[non_exhaustive]\n-    pub struct EthereumPayloadBuilder;\n-\n-    // Default implementation of [PayloadBuilder] for unit type\n-    impl<Pool, Client> PayloadBuilder<Pool, Client> for EthereumPayloadBuilder\n-    where\n-        Client: StateProviderFactory,\n-        Pool: TransactionPool,\n-    {\n-        type Attributes = EthPayloadBuilderAttributes;\n-        type BuiltPayload = EthBuiltPayload;\n-\n-        fn try_build(\n-            &self,\n-            args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,\n-        ) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError> {\n-            default_ethereum_payload_builder(args)\n-        }\n+use reth_basic_payload_builder::{\n+    commit_withdrawals, is_better_payload, pre_block_beacon_root_contract_call, BuildArguments,\n+    BuildOutcome, PayloadBuilder, PayloadConfig, WithdrawalsOutcome,\n+};\n+use reth_payload_builder::{\n+    error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes,\n+};\n+use reth_primitives::{\n+    constants::{\n+        eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE, EMPTY_RECEIPTS, EMPTY_TRANSACTIONS,\n+    },\n+    eip4844::calculate_excess_blob_gas,\n+    proofs,\n+    revm::env::tx_env_with_recovered,\n+    Block, Header, IntoRecoveredTransaction, Receipt, Receipts, EMPTY_OMMER_ROOT_HASH, U256,\n+};\n+use reth_provider::{BundleStateWithReceipts, StateProviderFactory};\n+use reth_revm::database::StateProviderDatabase;\n+use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool};\n+use revm::{\n+    db::states::bundle_state::BundleRetention,\n+    primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},\n+    DatabaseCommit, State,\n+};\n+use tracing::{debug, trace, warn};\n+\n+/// Ethereum payload builder\n+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]\n+#[non_exhaustive]\n+pub struct EthereumPayloadBuilder;\n+\n+// Default implementation of [PayloadBuilder] for unit type\n+impl<Pool, Client> PayloadBuilder<Pool, Client> for EthereumPayloadBuilder\n+where\n+    Client: StateProviderFactory,\n+    Pool: TransactionPool,\n+{\n+    type Attributes = EthPayloadBuilderAttributes;\n+    type BuiltPayload = EthBuiltPayload;\n+\n+    fn try_build(\n+        &self,\n+        args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,\n+    ) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError> {\n+        default_ethereum_payload_builder(args)\n+    }\n+\n+    fn build_empty_payload(\n+        client: &Client,\n+        config: PayloadConfig<Self::Attributes>,\n+    ) -> Result<EthBuiltPayload, PayloadBuilderError> {\n+        let extra_data = config.extra_data();\n+        let PayloadConfig {\n+            initialized_block_env,\n+            parent_block,\n+            attributes,\n+            chain_spec,\n+            initialized_cfg,\n+            ..\n+        } = config;\n+\n+        debug!(target: \"payload_builder\", parent_hash = ?parent_block.hash(), parent_number = parent_block.number, \"building empty payload\");\n \n-        fn build_empty_payload(\n-            client: &Client,\n-            config: PayloadConfig<Self::Attributes>,\n-        ) -> Result<EthBuiltPayload, PayloadBuilderError> {\n-            let extra_data = config.extra_data();\n-            let PayloadConfig {\n-                initialized_block_env,\n-                parent_block,\n-                attributes,\n-                chain_spec,\n-                initialized_cfg,\n-                ..\n-            } = config;\n-\n-            debug!(target: \"payload_builder\", parent_hash = ?parent_block.hash(), parent_number = parent_block.number, \"building empty payload\");\n-\n-            let state = client.state_by_block_hash(parent_block.hash()).map_err(|err| {\n+        let state = client.state_by_block_hash(parent_block.hash()).map_err(|err| {\n                 warn!(target: \"payload_builder\", parent_hash=%parent_block.hash(), %err, \"failed to get state for empty payload\");\n                 err\n             })?;\n-            let mut db = State::builder()\n-                .with_database_boxed(Box::new(StateProviderDatabase::new(&state)))\n-                .with_bundle_update()\n-                .build();\n-\n-            let base_fee = initialized_block_env.basefee.to::<u64>();\n-            let block_number = initialized_block_env.number.to::<u64>();\n-            let block_gas_limit: u64 =\n-                initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);\n-\n-            // apply eip-4788 pre block contract call\n-            pre_block_beacon_root_contract_call(\n+        let mut db = State::builder()\n+            .with_database_boxed(Box::new(StateProviderDatabase::new(&state)))\n+            .with_bundle_update()\n+            .build();\n+\n+        let base_fee = initialized_block_env.basefee.to::<u64>();\n+        let block_number = initialized_block_env.number.to::<u64>();\n+        let block_gas_limit: u64 = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);\n+\n+        // apply eip-4788 pre block contract call\n+        pre_block_beacon_root_contract_call(\n                 &mut db,\n                 &chain_spec,\n                 block_number,\n@@ -102,277 +96,28 @@ mod builder {\n                 err\n             })?;\n \n-            let WithdrawalsOutcome { withdrawals_root, withdrawals } =\n+        let WithdrawalsOutcome { withdrawals_root, withdrawals } =\n                 commit_withdrawals(&mut db, &chain_spec, attributes.timestamp, attributes.withdrawals.clone()).map_err(|err| {\n                     warn!(target: \"payload_builder\", parent_hash=%parent_block.hash(), %err, \"failed to commit withdrawals for empty payload\");\n                     err\n                 })?;\n \n-            // merge all transitions into bundle state, this would apply the withdrawal balance\n-            // changes and 4788 contract call\n-            db.merge_transitions(BundleRetention::PlainState);\n+        // merge all transitions into bundle state, this would apply the withdrawal balance\n+        // changes and 4788 contract call\n+        db.merge_transitions(BundleRetention::PlainState);\n \n-            // calculate the state root\n-            let bundle_state =\n-                BundleStateWithReceipts::new(db.take_bundle(), Receipts::new(), block_number);\n-            let state_root = state.state_root(&bundle_state).map_err(|err| {\n+        // calculate the state root\n+        let bundle_state =\n+            BundleStateWithReceipts::new(db.take_bundle(), Receipts::new(), block_number);\n+        let state_root = state.state_root(&bundle_state).map_err(|err| {\n                 warn!(target: \"payload_builder\", parent_hash=%parent_block.hash(), %err, \"failed to calculate state root for empty payload\");\n                 err\n             })?;\n \n-            let mut excess_blob_gas = None;\n-            let mut blob_gas_used = None;\n-\n-            if chain_spec.is_cancun_active_at_timestamp(attributes.timestamp) {\n-                excess_blob_gas = if chain_spec\n-                    .is_cancun_active_at_timestamp(parent_block.timestamp)\n-                {\n-                    let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default();\n-                    let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default();\n-                    Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used))\n-                } else {\n-                    // for the first post-fork block, both parent.blob_gas_used and\n-                    // parent.excess_blob_gas are evaluated as 0\n-                    Some(calculate_excess_blob_gas(0, 0))\n-                };\n-\n-                blob_gas_used = Some(0);\n-            }\n-\n-            let header = Header {\n-                parent_hash: parent_block.hash(),\n-                ommers_hash: EMPTY_OMMER_ROOT_HASH,\n-                beneficiary: initialized_block_env.coinbase,\n-                state_root,\n-                transactions_root: EMPTY_TRANSACTIONS,\n-                withdrawals_root,\n-                receipts_root: EMPTY_RECEIPTS,\n-                logs_bloom: Default::default(),\n-                timestamp: attributes.timestamp,\n-                mix_hash: attributes.prev_randao,\n-                nonce: BEACON_NONCE,\n-                base_fee_per_gas: Some(base_fee),\n-                number: parent_block.number + 1,\n-                gas_limit: block_gas_limit,\n-                difficulty: U256::ZERO,\n-                gas_used: 0,\n-                extra_data,\n-                blob_gas_used,\n-                excess_blob_gas,\n-                parent_beacon_block_root: attributes.parent_beacon_block_root,\n-            };\n-\n-            let block = Block { header, body: vec![], ommers: vec![], withdrawals };\n-            let sealed_block = block.seal_slow();\n-\n-            Ok(EthBuiltPayload::new(attributes.payload_id(), sealed_block, U256::ZERO))\n-        }\n-    }\n-\n-    /// Constructs an Ethereum transaction payload using the best transactions from the pool.\n-    ///\n-    /// Given build arguments including an Ethereum client, transaction pool,\n-    /// and configuration, this function creates a transaction payload. Returns\n-    /// a result indicating success with the payload or an error in case of failure.\n-    #[inline]\n-    pub fn default_ethereum_payload_builder<Pool, Client>(\n-        args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,\n-    ) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError>\n-    where\n-        Client: StateProviderFactory,\n-        Pool: TransactionPool,\n-    {\n-        let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;\n-\n-        let state_provider = client.state_by_block_hash(config.parent_block.hash())?;\n-        let state = StateProviderDatabase::new(&state_provider);\n-        let mut db = State::builder()\n-            .with_database_ref(cached_reads.as_db(&state))\n-            .with_bundle_update()\n-            .build();\n-        let extra_data = config.extra_data();\n-        let PayloadConfig {\n-            initialized_block_env,\n-            initialized_cfg,\n-            parent_block,\n-            attributes,\n-            chain_spec,\n-            ..\n-        } = config;\n-\n-        debug!(target: \"payload_builder\", id=%attributes.id, parent_hash = ?parent_block.hash(), parent_number = parent_block.number, \"building new payload\");\n-        let mut cumulative_gas_used = 0;\n-        let mut sum_blob_gas_used = 0;\n-        let block_gas_limit: u64 = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);\n-        let base_fee = initialized_block_env.basefee.to::<u64>();\n-\n-        let mut executed_txs = Vec::new();\n-\n-        let mut best_txs = pool.best_transactions_with_attributes(BestTransactionsAttributes::new(\n-            base_fee,\n-            initialized_block_env.get_blob_gasprice().map(|gasprice| gasprice as u64),\n-        ));\n-\n-        let mut total_fees = U256::ZERO;\n-\n-        let block_number = initialized_block_env.number.to::<u64>();\n-\n-        // apply eip-4788 pre block contract call\n-        pre_block_beacon_root_contract_call(\n-            &mut db,\n-            &chain_spec,\n-            block_number,\n-            &initialized_cfg,\n-            &initialized_block_env,\n-            &attributes,\n-        )?;\n-\n-        let mut receipts = Vec::new();\n-        while let Some(pool_tx) = best_txs.next() {\n-            // ensure we still have capacity for this transaction\n-            if cumulative_gas_used + pool_tx.gas_limit() > block_gas_limit {\n-                // we can't fit this transaction into the block, so we need to mark it as invalid\n-                // which also removes all dependent transaction from the iterator before we can\n-                // continue\n-                best_txs.mark_invalid(&pool_tx);\n-                continue\n-            }\n-\n-            // check if the job was cancelled, if so we can exit early\n-            if cancel.is_cancelled() {\n-                return Ok(BuildOutcome::Cancelled)\n-            }\n-\n-            // convert tx to a signed transaction\n-            let tx = pool_tx.to_recovered_transaction();\n-\n-            // There's only limited amount of blob space available per block, so we need to check if\n-            // the EIP-4844 can still fit in the block\n-            if let Some(blob_tx) = tx.transaction.as_eip4844() {\n-                let tx_blob_gas = blob_tx.blob_gas();\n-                if sum_blob_gas_used + tx_blob_gas > MAX_DATA_GAS_PER_BLOCK {\n-                    // we can't fit this _blob_ transaction into the block, so we mark it as\n-                    // invalid, which removes its dependent transactions from\n-                    // the iterator. This is similar to the gas limit condition\n-                    // for regular transactions above.\n-                    trace!(target: \"payload_builder\", tx=?tx.hash, ?sum_blob_gas_used, ?tx_blob_gas, \"skipping blob transaction because it would exceed the max data gas per block\");\n-                    best_txs.mark_invalid(&pool_tx);\n-                    continue\n-                }\n-            }\n-\n-            // Configure the environment for the block.\n-            let mut evm = revm::Evm::builder()\n-                .with_db(&mut db)\n-                .with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(\n-                    initialized_cfg.clone(),\n-                    initialized_block_env.clone(),\n-                    tx_env_with_recovered(&tx),\n-                ))\n-                .build();\n-\n-            let ResultAndState { result, state } = match evm.transact() {\n-                Ok(res) => res,\n-                Err(err) => {\n-                    match err {\n-                        EVMError::Transaction(err) => {\n-                            if matches!(err, InvalidTransaction::NonceTooLow { .. }) {\n-                                // if the nonce is too low, we can skip this transaction\n-                                trace!(target: \"payload_builder\", %err, ?tx, \"skipping nonce too low transaction\");\n-                            } else {\n-                                // if the transaction is invalid, we can skip it and all of its\n-                                // descendants\n-                                trace!(target: \"payload_builder\", %err, ?tx, \"skipping invalid transaction and its descendants\");\n-                                best_txs.mark_invalid(&pool_tx);\n-                            }\n-\n-                            continue\n-                        }\n-                        err => {\n-                            // this is an error that we should treat as fatal for this attempt\n-                            return Err(PayloadBuilderError::EvmExecutionError(err))\n-                        }\n-                    }\n-                }\n-            };\n-            // drop evm so db is released.\n-            drop(evm);\n-            // commit changes\n-            db.commit(state);\n-\n-            // add to the total blob gas used if the transaction successfully executed\n-            if let Some(blob_tx) = tx.transaction.as_eip4844() {\n-                let tx_blob_gas = blob_tx.blob_gas();\n-                sum_blob_gas_used += tx_blob_gas;\n-\n-                // if we've reached the max data gas per block, we can skip blob txs entirely\n-                if sum_blob_gas_used == MAX_DATA_GAS_PER_BLOCK {\n-                    best_txs.skip_blobs();\n-                }\n-            }\n-\n-            let gas_used = result.gas_used();\n-\n-            // add gas used by the transaction to cumulative gas used, before creating the receipt\n-            cumulative_gas_used += gas_used;\n-\n-            // Push transaction changeset and calculate header bloom filter for receipt.\n-            receipts.push(Some(Receipt {\n-                tx_type: tx.tx_type(),\n-                success: result.is_success(),\n-                cumulative_gas_used,\n-                logs: result.logs().into_iter().map(Into::into).collect(),\n-            }));\n-\n-            // update add to total fees\n-            let miner_fee = tx\n-                .effective_tip_per_gas(Some(base_fee))\n-                .expect(\"fee is always valid; execution succeeded\");\n-            total_fees += U256::from(miner_fee) * U256::from(gas_used);\n-\n-            // append transaction to the list of executed transactions\n-            executed_txs.push(tx.into_signed());\n-        }\n-\n-        // check if we have a better block\n-        if !is_better_payload(best_payload.as_ref(), total_fees) {\n-            // can skip building the block\n-            return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads })\n-        }\n-\n-        let WithdrawalsOutcome { withdrawals_root, withdrawals } =\n-            commit_withdrawals(&mut db, &chain_spec, attributes.timestamp, attributes.withdrawals)?;\n-\n-        // merge all transitions into bundle state, this would apply the withdrawal balance changes\n-        // and 4788 contract call\n-        db.merge_transitions(BundleRetention::PlainState);\n-\n-        let bundle = BundleStateWithReceipts::new(\n-            db.take_bundle(),\n-            Receipts::from_vec(vec![receipts]),\n-            block_number,\n-        );\n-        let receipts_root = bundle.receipts_root_slow(block_number).expect(\"Number is in range\");\n-        let logs_bloom = bundle.block_logs_bloom(block_number).expect(\"Number is in range\");\n-\n-        // calculate the state root\n-        let state_root = state_provider.state_root(&bundle)?;\n-\n-        // create the block header\n-        let transactions_root = proofs::calculate_transaction_root(&executed_txs);\n-\n-        // initialize empty blob sidecars at first. If cancun is active then this will\n-        let mut blob_sidecars = Vec::new();\n         let mut excess_blob_gas = None;\n         let mut blob_gas_used = None;\n \n-        // only determine cancun fields when active\n         if chain_spec.is_cancun_active_at_timestamp(attributes.timestamp) {\n-            // grab the blob sidecars from the executed txs\n-            blob_sidecars = pool.get_all_blobs_exact(\n-                executed_txs.iter().filter(|tx| tx.is_eip4844()).map(|tx| tx.hash).collect(),\n-            )?;\n-\n             excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_block.timestamp) {\n                 let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default();\n                 let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default();\n@@ -383,43 +128,289 @@ mod builder {\n                 Some(calculate_excess_blob_gas(0, 0))\n             };\n \n-            blob_gas_used = Some(sum_blob_gas_used);\n+            blob_gas_used = Some(0);\n         }\n \n         let header = Header {\n             parent_hash: parent_block.hash(),\n             ommers_hash: EMPTY_OMMER_ROOT_HASH,\n             beneficiary: initialized_block_env.coinbase,\n             state_root,\n-            transactions_root,\n-            receipts_root,\n+            transactions_root: EMPTY_TRANSACTIONS,\n             withdrawals_root,\n-            logs_bloom,\n+            receipts_root: EMPTY_RECEIPTS,\n+            logs_bloom: Default::default(),\n             timestamp: attributes.timestamp,\n             mix_hash: attributes.prev_randao,\n             nonce: BEACON_NONCE,\n             base_fee_per_gas: Some(base_fee),\n             number: parent_block.number + 1,\n             gas_limit: block_gas_limit,\n             difficulty: U256::ZERO,\n-            gas_used: cumulative_gas_used,\n+            gas_used: 0,\n             extra_data,\n-            parent_beacon_block_root: attributes.parent_beacon_block_root,\n             blob_gas_used,\n             excess_blob_gas,\n+            parent_beacon_block_root: attributes.parent_beacon_block_root,\n         };\n \n-        // seal the block\n-        let block = Block { header, body: executed_txs, ommers: vec![], withdrawals };\n-\n+        let block = Block { header, body: vec![], ommers: vec![], withdrawals };\n         let sealed_block = block.seal_slow();\n-        debug!(target: \"payload_builder\", ?sealed_block, \"sealed built block\");\n \n-        let mut payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees);\n+        Ok(EthBuiltPayload::new(attributes.payload_id(), sealed_block, U256::ZERO))\n+    }\n+}\n \n-        // extend the payload with the blob sidecars from the executed txs\n-        payload.extend_sidecars(blob_sidecars);\n+/// Constructs an Ethereum transaction payload using the best transactions from the pool.\n+///\n+/// Given build arguments including an Ethereum client, transaction pool,\n+/// and configuration, this function creates a transaction payload. Returns\n+/// a result indicating success with the payload or an error in case of failure.\n+#[inline]\n+pub fn default_ethereum_payload_builder<Pool, Client>(\n+    args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,\n+) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError>\n+where\n+    Client: StateProviderFactory,\n+    Pool: TransactionPool,\n+{\n+    let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;\n+\n+    let state_provider = client.state_by_block_hash(config.parent_block.hash())?;\n+    let state = StateProviderDatabase::new(&state_provider);\n+    let mut db =\n+        State::builder().with_database_ref(cached_reads.as_db(&state)).with_bundle_update().build();\n+    let extra_data = config.extra_data();\n+    let PayloadConfig {\n+        initialized_block_env,\n+        initialized_cfg,\n+        parent_block,\n+        attributes,\n+        chain_spec,\n+        ..\n+    } = config;\n+\n+    debug!(target: \"payload_builder\", id=%attributes.id, parent_hash = ?parent_block.hash(), parent_number = parent_block.number, \"building new payload\");\n+    let mut cumulative_gas_used = 0;\n+    let mut sum_blob_gas_used = 0;\n+    let block_gas_limit: u64 = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);\n+    let base_fee = initialized_block_env.basefee.to::<u64>();\n+\n+    let mut executed_txs = Vec::new();\n+\n+    let mut best_txs = pool.best_transactions_with_attributes(BestTransactionsAttributes::new(\n+        base_fee,\n+        initialized_block_env.get_blob_gasprice().map(|gasprice| gasprice as u64),\n+    ));\n+\n+    let mut total_fees = U256::ZERO;\n+\n+    let block_number = initialized_block_env.number.to::<u64>();\n+\n+    // apply eip-4788 pre block contract call\n+    pre_block_beacon_root_contract_call(\n+        &mut db,\n+        &chain_spec,\n+        block_number,\n+        &initialized_cfg,\n+        &initialized_block_env,\n+        &attributes,\n+    )?;\n+\n+    let mut receipts = Vec::new();\n+    while let Some(pool_tx) = best_txs.next() {\n+        // ensure we still have capacity for this transaction\n+        if cumulative_gas_used + pool_tx.gas_limit() > block_gas_limit {\n+            // we can't fit this transaction into the block, so we need to mark it as invalid\n+            // which also removes all dependent transaction from the iterator before we can\n+            // continue\n+            best_txs.mark_invalid(&pool_tx);\n+            continue\n+        }\n \n-        Ok(BuildOutcome::Better { payload, cached_reads })\n+        // check if the job was cancelled, if so we can exit early\n+        if cancel.is_cancelled() {\n+            return Ok(BuildOutcome::Cancelled)\n+        }\n+\n+        // convert tx to a signed transaction\n+        let tx = pool_tx.to_recovered_transaction();\n+\n+        // There's only limited amount of blob space available per block, so we need to check if\n+        // the EIP-4844 can still fit in the block\n+        if let Some(blob_tx) = tx.transaction.as_eip4844() {\n+            let tx_blob_gas = blob_tx.blob_gas();\n+            if sum_blob_gas_used + tx_blob_gas > MAX_DATA_GAS_PER_BLOCK {\n+                // we can't fit this _blob_ transaction into the block, so we mark it as\n+                // invalid, which removes its dependent transactions from\n+                // the iterator. This is similar to the gas limit condition\n+                // for regular transactions above.\n+                trace!(target: \"payload_builder\", tx=?tx.hash, ?sum_blob_gas_used, ?tx_blob_gas, \"skipping blob transaction because it would exceed the max data gas per block\");\n+                best_txs.mark_invalid(&pool_tx);\n+                continue\n+            }\n+        }\n+\n+        // Configure the environment for the block.\n+        let mut evm = revm::Evm::builder()\n+            .with_db(&mut db)\n+            .with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(\n+                initialized_cfg.clone(),\n+                initialized_block_env.clone(),\n+                tx_env_with_recovered(&tx),\n+            ))\n+            .build();\n+\n+        let ResultAndState { result, state } = match evm.transact() {\n+            Ok(res) => res,\n+            Err(err) => {\n+                match err {\n+                    EVMError::Transaction(err) => {\n+                        if matches!(err, InvalidTransaction::NonceTooLow { .. }) {\n+                            // if the nonce is too low, we can skip this transaction\n+                            trace!(target: \"payload_builder\", %err, ?tx, \"skipping nonce too low transaction\");\n+                        } else {\n+                            // if the transaction is invalid, we can skip it and all of its\n+                            // descendants\n+                            trace!(target: \"payload_builder\", %err, ?tx, \"skipping invalid transaction and its descendants\");\n+                            best_txs.mark_invalid(&pool_tx);\n+                        }\n+\n+                        continue\n+                    }\n+                    err => {\n+                        // this is an error that we should treat as fatal for this attempt\n+                        return Err(PayloadBuilderError::EvmExecutionError(err))\n+                    }\n+                }\n+            }\n+        };\n+        // drop evm so db is released.\n+        drop(evm);\n+        // commit changes\n+        db.commit(state);\n+\n+        // add to the total blob gas used if the transaction successfully executed\n+        if let Some(blob_tx) = tx.transaction.as_eip4844() {\n+            let tx_blob_gas = blob_tx.blob_gas();\n+            sum_blob_gas_used += tx_blob_gas;\n+\n+            // if we've reached the max data gas per block, we can skip blob txs entirely\n+            if sum_blob_gas_used == MAX_DATA_GAS_PER_BLOCK {\n+                best_txs.skip_blobs();\n+            }\n+        }\n+\n+        let gas_used = result.gas_used();\n+\n+        // add gas used by the transaction to cumulative gas used, before creating the receipt\n+        cumulative_gas_used += gas_used;\n+\n+        // Push transaction changeset and calculate header bloom filter for receipt.\n+        #[allow(clippy::needless_update)] // side-effect of optimism fields\n+        receipts.push(Some(Receipt {\n+            tx_type: tx.tx_type(),\n+            success: result.is_success(),\n+            cumulative_gas_used,\n+            logs: result.logs().into_iter().map(Into::into).collect(),\n+            ..Default::default()\n+        }));\n+\n+        // update add to total fees\n+        let miner_fee = tx\n+            .effective_tip_per_gas(Some(base_fee))\n+            .expect(\"fee is always valid; execution succeeded\");\n+        total_fees += U256::from(miner_fee) * U256::from(gas_used);\n+\n+        // append transaction to the list of executed transactions\n+        executed_txs.push(tx.into_signed());\n     }\n+\n+    // check if we have a better block\n+    if !is_better_payload(best_payload.as_ref(), total_fees) {\n+        // can skip building the block\n+        return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads })\n+    }\n+\n+    let WithdrawalsOutcome { withdrawals_root, withdrawals } =\n+        commit_withdrawals(&mut db, &chain_spec, attributes.timestamp, attributes.withdrawals)?;\n+\n+    // merge all transitions into bundle state, this would apply the withdrawal balance changes\n+    // and 4788 contract call\n+    db.merge_transitions(BundleRetention::PlainState);\n+\n+    let bundle = BundleStateWithReceipts::new(\n+        db.take_bundle(),\n+        Receipts::from_vec(vec![receipts]),\n+        block_number,\n+    );\n+    let receipts_root = bundle.receipts_root_slow(block_number).expect(\"Number is in range\");\n+    let logs_bloom = bundle.block_logs_bloom(block_number).expect(\"Number is in range\");\n+\n+    // calculate the state root\n+    let state_root = state_provider.state_root(&bundle)?;\n+\n+    // create the block header\n+    let transactions_root = proofs::calculate_transaction_root(&executed_txs);\n+\n+    // initialize empty blob sidecars at first. If cancun is active then this will\n+    let mut blob_sidecars = Vec::new();\n+    let mut excess_blob_gas = None;\n+    let mut blob_gas_used = None;\n+\n+    // only determine cancun fields when active\n+    if chain_spec.is_cancun_active_at_timestamp(attributes.timestamp) {\n+        // grab the blob sidecars from the executed txs\n+        blob_sidecars = pool.get_all_blobs_exact(\n+            executed_txs.iter().filter(|tx| tx.is_eip4844()).map(|tx| tx.hash).collect(),\n+        )?;\n+\n+        excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_block.timestamp) {\n+            let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default();\n+            let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default();\n+            Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used))\n+        } else {\n+            // for the first post-fork block, both parent.blob_gas_used and\n+            // parent.excess_blob_gas are evaluated as 0\n+            Some(calculate_excess_blob_gas(0, 0))\n+        };\n+\n+        blob_gas_used = Some(sum_blob_gas_used);\n+    }\n+\n+    let header = Header {\n+        parent_hash: parent_block.hash(),\n+        ommers_hash: EMPTY_OMMER_ROOT_HASH,\n+        beneficiary: initialized_block_env.coinbase,\n+        state_root,\n+        transactions_root,\n+        receipts_root,\n+        withdrawals_root,\n+        logs_bloom,\n+        timestamp: attributes.timestamp,\n+        mix_hash: attributes.prev_randao,\n+        nonce: BEACON_NONCE,\n+        base_fee_per_gas: Some(base_fee),\n+        number: parent_block.number + 1,\n+        gas_limit: block_gas_limit,\n+        difficulty: U256::ZERO,\n+        gas_used: cumulative_gas_used,\n+        extra_data,\n+        parent_beacon_block_root: attributes.parent_beacon_block_root,\n+        blob_gas_used,\n+        excess_blob_gas,\n+    };\n+\n+    // seal the block\n+    let block = Block { header, body: executed_txs, ommers: vec![], withdrawals };\n+\n+    let sealed_block = block.seal_slow();\n+    debug!(target: \"payload_builder\", ?sealed_block, \"sealed built block\");\n+\n+    let mut payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees);\n+\n+    // extend the payload with the blob sidecars from the executed txs\n+    payload.extend_sidecars(blob_sidecars);\n+\n+    Ok(BuildOutcome::Better { payload, cached_reads })\n }"},{"sha":"699e2de27f885800e5b2b35ff0563e2c7573ff32","filename":"crates/payload/optimism/src/lib.rs","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Foptimism%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fpayload%2Foptimism%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fpayload%2Foptimism%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -503,7 +503,7 @@ mod builder {\n             block_number,\n         );\n         let receipts_root = bundle\n-            .receipts_root_slow(\n+            .optimism_receipts_root_slow(\n                 block_number,\n                 chain_spec.as_ref(),\n                 attributes.payload_attributes.timestamp,"},{"sha":"9741d5ddd13f89a0c430b44b93fb5f2189548215","filename":"crates/primitives/src/receipt.rs","status":"modified","additions":3,"deletions":8,"changes":11,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fprimitives%2Fsrc%2Freceipt.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fprimitives%2Fsrc%2Freceipt.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fprimitives%2Fsrc%2Freceipt.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -1,7 +1,3 @@\n-#[cfg(not(feature = \"optimism\"))]\n-use crate::proofs::calculate_receipt_root_ref;\n-#[cfg(feature = \"optimism\")]\n-use crate::proofs::calculate_receipt_root_ref_optimism;\n use crate::{\n     compression::{RECEIPT_COMPRESSOR, RECEIPT_DECOMPRESSOR},\n     logs_bloom, Bloom, Log, PruneSegmentError, TxType, B256,\n@@ -97,22 +93,21 @@ impl Receipts {\n     }\n \n     /// Retrieves the receipt root for all recorded receipts from index.\n-    #[cfg(not(feature = \"optimism\"))]\n     pub fn root_slow(&self, index: usize) -> Option<B256> {\n-        Some(calculate_receipt_root_ref(\n+        Some(crate::proofs::calculate_receipt_root_ref(\n             &self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,\n         ))\n     }\n \n     /// Retrieves the receipt root for all recorded receipts from index.\n     #[cfg(feature = \"optimism\")]\n-    pub fn root_slow(\n+    pub fn optimism_root_slow(\n         &self,\n         index: usize,\n         chain_spec: &crate::ChainSpec,\n         timestamp: u64,\n     ) -> Option<B256> {\n-        Some(calculate_receipt_root_ref_optimism(\n+        Some(crate::proofs::calculate_receipt_root_ref_optimism(\n             &self.receipt_vec[index].iter().map(Option::as_ref).collect::<Option<Vec<_>>>()?,\n             chain_spec,\n             timestamp,"},{"sha":"754ead15d3cc5956a827439b59d4d56633e70e51","filename":"crates/rpc/rpc/src/eth/api/pending_block.rs","status":"modified","additions":6,"deletions":3,"changes":9,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Frpc%2Frpc%2Fsrc%2Feth%2Fapi%2Fpending_block.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Frpc%2Frpc%2Fsrc%2Feth%2Fapi%2Fpending_block.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Frpc%2Frpc%2Fsrc%2Feth%2Fapi%2Fpending_block.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -215,15 +215,18 @@ impl PendingBlockEnv {\n             block_number,\n         );\n \n+        #[cfg(feature = \"optimism\")]\n         let receipts_root = bundle\n-            .receipts_root_slow(\n+            .optimism_receipts_root_slow(\n                 block_number,\n-                #[cfg(feature = \"optimism\")]\n                 chain_spec.as_ref(),\n-                #[cfg(feature = \"optimism\")]\n                 block_env.timestamp.to::<u64>(),\n             )\n             .expect(\"Block is present\");\n+\n+        #[cfg(not(feature = \"optimism\"))]\n+        let receipts_root = bundle.receipts_root_slow(block_number).expect(\"Block is present\");\n+\n         let logs_bloom = bundle.block_logs_bloom(block_number).expect(\"Block is present\");\n \n         // calculate the state root"},{"sha":"5b900ec742cc0b90cb165a892891b3f416f855a0","filename":"crates/storage/provider/src/bundle_state/bundle_state_with_receipts.rs","status":"modified","additions":10,"deletions":3,"changes":13,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fstorage%2Fprovider%2Fsrc%2Fbundle_state%2Fbundle_state_with_receipts.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Fstorage%2Fprovider%2Fsrc%2Fbundle_state%2Fbundle_state_with_receipts.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Fstorage%2Fprovider%2Fsrc%2Fbundle_state%2Fbundle_state_with_receipts.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -163,22 +163,29 @@ impl BundleStateWithReceipts {\n     /// Returns the receipt root for all recorded receipts.\n     /// Note: this function calculated Bloom filters for every receipt and created merkle trees\n     /// of receipt. This is a expensive operation.\n-    #[cfg(not(feature = \"optimism\"))]\n+    #[allow(unused_variables)]\n     pub fn receipts_root_slow(&self, block_number: BlockNumber) -> Option<B256> {\n+        #[cfg(feature = \"optimism\")]\n+        panic!(\"This should not be called in optimism mode. Use `optimism_receipts_root_slow` instead.\");\n+        #[cfg(not(feature = \"optimism\"))]\n         self.receipts.root_slow(self.block_number_to_index(block_number)?)\n     }\n \n     /// Returns the receipt root for all recorded receipts.\n     /// Note: this function calculated Bloom filters for every receipt and created merkle trees\n     /// of receipt. This is a expensive operation.\n     #[cfg(feature = \"optimism\")]\n-    pub fn receipts_root_slow(\n+    pub fn optimism_receipts_root_slow(\n         &self,\n         block_number: BlockNumber,\n         chain_spec: &reth_primitives::ChainSpec,\n         timestamp: u64,\n     ) -> Option<B256> {\n-        self.receipts.root_slow(self.block_number_to_index(block_number)?, chain_spec, timestamp)\n+        self.receipts.optimism_root_slow(\n+            self.block_number_to_index(block_number)?,\n+            chain_spec,\n+            timestamp,\n+        )\n     }\n \n     /// Returns reference to receipts."},{"sha":"1901c891acae76366fb00263fc8f1945013e9f96","filename":"crates/tasks/src/lib.rs","status":"modified","additions":0,"deletions":6,"changes":6,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Ftasks%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Ftasks%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Ftasks%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -298,12 +298,6 @@ impl TaskExecutor {\n         &self.on_shutdown\n     }\n \n-    /// Runs a future to completion on this Handle's associated Runtime.\n-    #[track_caller]\n-    pub fn block_on<F: Future>(&self, future: F) -> F::Output {\n-        self.handle.block_on(future)\n-    }\n-\n     /// Spawns a future on the tokio runtime depending on the [TaskKind]\n     fn spawn_on_rt<F>(&self, fut: F, task_kind: TaskKind) -> JoinHandle<()>\n     where"},{"sha":"fa374351dfbf65889faf071015b73266d6c15472","filename":"crates/transaction-pool/src/lib.rs","status":"modified","additions":0,"deletions":2,"changes":2,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Ftransaction-pool%2Fsrc%2Flib.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/crates%2Ftransaction-pool%2Fsrc%2Flib.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/crates%2Ftransaction-pool%2Fsrc%2Flib.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -242,8 +242,6 @@ where\n     ) -> Vec<(TxHash, TransactionValidationOutcome<V::Transaction>)> {\n         futures_util::future::join_all(transactions.into_iter().map(|tx| self.validate(origin, tx)))\n             .await\n-            .into_iter()\n-            .collect()\n     }\n \n     /// Validates the given transaction"},{"sha":"960dd86d02bb5b91c8bdc96f2c7e7277612ca9e5","filename":"examples/additional-rpc-namespace-in-cli/Cargo.toml","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fadditional-rpc-namespace-in-cli%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fadditional-rpc-namespace-in-cli%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fadditional-rpc-namespace-in-cli%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -8,6 +8,7 @@ license.workspace = true\n [dependencies]\n reth.workspace = true\n reth-transaction-pool.workspace = true\n+reth-node-ethereum.workspace = true\n \n clap = { workspace = true, features = [\"derive\"] }\n jsonrpsee = { workspace = true, features = [\"server\", \"macros\"] }"},{"sha":"a4713f931c940db6b4f2ffc06964a2e6be863839","filename":"examples/additional-rpc-namespace-in-cli/src/main.rs","status":"modified","additions":27,"deletions":41,"changes":68,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fadditional-rpc-namespace-in-cli%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fadditional-rpc-namespace-in-cli%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fadditional-rpc-namespace-in-cli%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -14,24 +14,38 @@\n \n use clap::Parser;\n use jsonrpsee::{core::RpcResult, proc_macros::rpc};\n-use reth::cli::{\n-    components::{RethNodeComponents, RethRpcComponents},\n-    config::RethRpcConfig,\n-    ext::{RethCliExt, RethNodeCommandConfig},\n-    Cli,\n-};\n+use reth::cli::Cli;\n+use reth_node_ethereum::EthereumNode;\n use reth_transaction_pool::TransactionPool;\n \n fn main() {\n-    Cli::<MyRethCliExt>::parse().run().unwrap();\n-}\n+    Cli::<RethCliTxpoolExt>::parse()\n+        .run(|builder, args| async move {\n+            let handle = builder\n+                .node(EthereumNode::default())\n+                .extend_rpc_modules(move |ctx| {\n+                    if !args.enable_ext {\n+                        return Ok(())\n+                    }\n+\n+                    // here we get the configured pool.\n+                    let pool = ctx.pool().clone();\n+\n+                    let ext = TxpoolExt { pool };\n+\n+                    // now we merge our extension namespace into all configured transports\n+                    ctx.modules.merge_configured(ext.into_rpc())?;\n \n-/// The type that tells the reth CLI what extensions to use\n-struct MyRethCliExt;\n+                    println!(\"txpool extension enabled\");\n \n-impl RethCliExt for MyRethCliExt {\n-    /// This tells the reth CLI to install the `txpool` rpc namespace via `RethCliTxpoolExt`\n-    type Node = RethCliTxpoolExt;\n+                    Ok(())\n+                })\n+                .launch()\n+                .await?;\n+\n+            handle.wait_for_node_exit().await\n+        })\n+        .unwrap();\n }\n \n /// Our custom cli args extension that adds one flag to reth default CLI.\n@@ -42,34 +56,6 @@ struct RethCliTxpoolExt {\n     pub enable_ext: bool,\n }\n \n-impl RethNodeCommandConfig for RethCliTxpoolExt {\n-    // This is the entrypoint for the CLI to extend the RPC server with custom rpc namespaces.\n-    fn extend_rpc_modules<Conf, Reth>(\n-        &mut self,\n-        _config: &Conf,\n-        _components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        if !self.enable_ext {\n-            return Ok(())\n-        }\n-\n-        // here we get the configured pool type from the CLI.\n-        let pool = rpc_components.registry.pool().clone();\n-        let ext = TxpoolExt { pool };\n-\n-        // now we merge our extension namespace into all configured transports\n-        rpc_components.modules.merge_configured(ext.into_rpc())?;\n-\n-        println!(\"txpool extension enabled\");\n-        Ok(())\n-    }\n-}\n-\n /// trait interface for a custom rpc namespace: `txpool`\n ///\n /// This defines an additional namespace where all methods are configured as trait functions."},{"sha":"bbf64b73c8a0de39f73b93a330b736eb1faa6734","filename":"examples/beacon-api-sse/Cargo.toml","status":"modified","additions":2,"deletions":3,"changes":5,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fbeacon-api-sse%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fbeacon-api-sse%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fbeacon-api-sse%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -7,10 +7,9 @@ license.workspace = true\n \n [dependencies]\n reth.workspace = true\n-eyre.workspace = true\n+reth-node-ethereum.workspace = true\n+\n clap.workspace = true\n-serde.workspace = true\n-serde_json.workspace = true\n tracing.workspace = true\n futures-util.workspace = true\n tokio = { workspace = true, features = [\"time\"] }"},{"sha":"9df64ce43a3c16b73c8daa8df1706240c5c5ef2c","filename":"examples/beacon-api-sse/src/main.rs","status":"modified","additions":11,"deletions":25,"changes":36,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fbeacon-api-sse%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fbeacon-api-sse%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fbeacon-api-sse%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -15,33 +15,26 @@\n //!\n //! See lighthouse beacon Node API: <https://lighthouse-book.sigmaprime.io/api-bn.html#beacon-node-api>\n \n+#![warn(unused_crate_dependencies)]\n+\n use clap::Parser;\n use futures_util::stream::StreamExt;\n use mev_share_sse::{client::EventStream, EventClient};\n-use reth::{\n-    cli::{\n-        components::RethNodeComponents,\n-        ext::{RethCliExt, RethNodeCommandConfig},\n-        Cli,\n-    },\n-    rpc::types::beacon::events::PayloadAttributesEvent,\n-    tasks::TaskSpawner,\n-};\n+use reth::{cli::Cli, rpc::types::beacon::events::PayloadAttributesEvent};\n+use reth_node_ethereum::EthereumNode;\n use std::net::{IpAddr, Ipv4Addr};\n use tracing::{info, warn};\n \n fn main() {\n-    Cli::<BeaconEventsExt>::parse().run().unwrap();\n-}\n+    Cli::<BeaconEventsConfig>::parse()\n+        .run(|builder, args| async move {\n+            let handle = builder.node(EthereumNode::default()).launch().await?;\n \n-/// The type that tells the reth CLI what extensions to use\n-#[derive(Debug, Default)]\n-#[non_exhaustive]\n-struct BeaconEventsExt;\n+            handle.node.task_executor.spawn(Box::pin(args.run()));\n \n-impl RethCliExt for BeaconEventsExt {\n-    /// This tells the reth CLI to install additional CLI arguments\n-    type Node = BeaconEventsConfig;\n+            handle.wait_for_node_exit().await\n+        })\n+        .unwrap();\n }\n \n /// Our custom cli args extension that adds one flag to reth default CLI.\n@@ -95,13 +88,6 @@ impl BeaconEventsConfig {\n     }\n }\n \n-impl RethNodeCommandConfig for BeaconEventsConfig {\n-    fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {\n-        components.task_executor().spawn(Box::pin(self.clone().run()));\n-        Ok(())\n-    }\n-}\n-\n #[cfg(test)]\n mod tests {\n     use super::*;"},{"sha":"2acac14ee78e781c2852f7de22e9604704040c88","filename":"examples/cli-extension-event-hooks/Cargo.toml","status":"modified","additions":1,"deletions":2,"changes":3,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcli-extension-event-hooks%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcli-extension-event-hooks%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcli-extension-event-hooks%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -7,5 +7,4 @@ license.workspace = true\n \n [dependencies]\n reth.workspace = true\n-clap.workspace = true\n-eyre.workspace = true\n\\ No newline at end of file\n+reth-node-ethereum.workspace = true\n\\ No newline at end of file"},{"sha":"9f09d7a3cb1fdad654515ea872475a8e109782ca","filename":"examples/cli-extension-event-hooks/src/main.rs","status":"modified","additions":23,"deletions":31,"changes":54,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcli-extension-event-hooks%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcli-extension-event-hooks%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcli-extension-event-hooks%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -15,38 +15,30 @@\n //! > \"Node started\"\n //! once the node has been started.\n \n-use clap::Parser;\n-use reth::cli::{\n-    components::RethNodeComponents,\n-    ext::{NoArgsCliExt, RethNodeCommandConfig},\n-    Cli,\n-};\n+use reth::cli::Cli;\n+use reth_node_ethereum::EthereumNode;\n \n fn main() {\n-    Cli::<NoArgsCliExt<MyRethConfig>>::parse()\n-        .with_node_extension(MyRethConfig::default())\n-        .run()\n-        .unwrap();\n-}\n+    Cli::parse_args()\n+        .run(|builder, _| async move {\n+            let handle = builder\n+                .node(EthereumNode::default())\n+                .on_node_started(|_ctx| {\n+                    println!(\"Node started\");\n+                    Ok(())\n+                })\n+                .on_rpc_started(|_ctx, _handles| {\n+                    println!(\"RPC started\");\n+                    Ok(())\n+                })\n+                .on_component_initialized(|_ctx| {\n+                    println!(\"All components initialized\");\n+                    Ok(())\n+                })\n+                .launch()\n+                .await?;\n \n-/// Our custom cli args extension that adds one flag to reth default CLI.\n-#[derive(Debug, Clone, Copy, Default)]\n-#[non_exhaustive]\n-struct MyRethConfig;\n-\n-impl RethNodeCommandConfig for MyRethConfig {\n-    fn on_components_initialized<Reth: RethNodeComponents>(\n-        &mut self,\n-        _components: &Reth,\n-    ) -> eyre::Result<()> {\n-        println!(\"All components initialized\");\n-        Ok(())\n-    }\n-    fn on_node_started<Reth: RethNodeComponents>(\n-        &mut self,\n-        _components: &Reth,\n-    ) -> eyre::Result<()> {\n-        println!(\"Node started\");\n-        Ok(())\n-    }\n+            handle.wait_for_node_exit().await\n+        })\n+        .unwrap();\n }"},{"sha":"3cd624cea1fc88ab30bc351c8d307947dd89d5aa","filename":"examples/custom-dev-node/Cargo.toml","status":"added","additions":18,"deletions":0,"changes":18,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-dev-node%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-dev-node%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-dev-node%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,18 @@\n+[package]\n+name = \"custom-dev-node\"\n+version = \"0.0.0\"\n+publish = false\n+edition.workspace = true\n+license.workspace = true\n+\n+\n+[dependencies]\n+reth.workspace = true\n+reth-node-core.workspace = true\n+reth-primitives.workspace = true\n+reth-node-ethereum.workspace = true\n+futures-util.workspace = true\n+\n+eyre.workspace = true\n+tokio.workspace = true\n+serde_json.workspace = true"},{"sha":"b8a2c0bfb771812d7835bec01d4908a301fac065","filename":"examples/custom-dev-node/src/main.rs","status":"added","additions":96,"deletions":0,"changes":96,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-dev-node%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-dev-node%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-dev-node%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,96 @@\n+//! This example shows how to run a custom dev node programmatically and submit a transaction\n+//! through rpc.\n+\n+#![warn(unused_crate_dependencies)]\n+\n+use futures_util::StreamExt;\n+use reth::{\n+    builder::{NodeBuilder, NodeHandle},\n+    providers::CanonStateSubscriptions,\n+    rpc::eth::EthTransactions,\n+    tasks::TaskManager,\n+};\n+use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};\n+use reth_node_ethereum::EthereumNode;\n+use reth_primitives::{b256, hex, ChainSpec, Genesis};\n+use std::sync::Arc;\n+\n+#[tokio::main]\n+async fn main() -> eyre::Result<()> {\n+    let tasks = TaskManager::current();\n+\n+    // create node config\n+    let node_config = NodeConfig::test()\n+        .dev()\n+        .with_rpc(RpcServerArgs::default().with_http())\n+        .with_chain(custom_chain());\n+\n+    let NodeHandle { mut node, node_exit_future } = NodeBuilder::new(node_config)\n+        .testing_node(tasks.executor())\n+        .node(EthereumNode::default())\n+        .launch()\n+        .await?;\n+\n+    let mut notifications = node.provider.canonical_state_stream();\n+\n+    // submit tx through rpc\n+    let raw_tx = hex!(\"02f876820a28808477359400847735940082520894ab0840c0e43688012c1adb0f5e3fc665188f83d28a029d394a5d630544000080c080a0a044076b7e67b5deecc63f61a8d7913fab86ca365b344b5759d1fe3563b4c39ea019eab979dd000da04dfc72bb0377c092d30fd9e1cab5ae487de49586cc8b0090\");\n+\n+    let eth_api = node.rpc_registry.eth_api();\n+\n+    let hash = eth_api.send_raw_transaction(raw_tx.into()).await?;\n+\n+    let expected = b256!(\"b1c6512f4fc202c04355fbda66755e0e344b152e633010e8fd75ecec09b63398\");\n+\n+    assert_eq!(hash, expected);\n+    println!(\"submitted transaction: {hash}\");\n+\n+    let head = notifications.next().await.unwrap();\n+\n+    let tx = head.tip().transactions().next().unwrap();\n+    assert_eq!(tx.hash(), hash);\n+    println!(\"mined transaction: {hash}\");\n+\n+    node_exit_future.await\n+}\n+\n+fn custom_chain() -> Arc<ChainSpec> {\n+    let custom_genesis = r#\"\n+{\n+    \"nonce\": \"0x42\",\n+    \"timestamp\": \"0x0\",\n+    \"extraData\": \"0x5343\",\n+    \"gasLimit\": \"0x1388\",\n+    \"difficulty\": \"0x400000000\",\n+    \"mixHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n+    \"coinbase\": \"0x0000000000000000000000000000000000000000\",\n+    \"alloc\": {\n+        \"0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b\": {\n+            \"balance\": \"0x4a47e3c12448f4ad000000\"\n+        }\n+    },\n+    \"number\": \"0x0\",\n+    \"gasUsed\": \"0x0\",\n+    \"parentHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n+    \"config\": {\n+        \"ethash\": {},\n+        \"chainId\": 2600,\n+        \"homesteadBlock\": 0,\n+        \"eip150Block\": 0,\n+        \"eip155Block\": 0,\n+        \"eip158Block\": 0,\n+        \"byzantiumBlock\": 0,\n+        \"constantinopleBlock\": 0,\n+        \"petersburgBlock\": 0,\n+        \"istanbulBlock\": 0,\n+        \"berlinBlock\": 0,\n+        \"londonBlock\": 0,\n+        \"terminalTotalDifficulty\": 0,\n+        \"terminalTotalDifficultyPassed\": true,\n+        \"shanghaiTime\": 0\n+    }\n+}\n+\"#;\n+    let genesis: Genesis = serde_json::from_str(custom_genesis).unwrap();\n+    Arc::new(genesis.into())\n+}"},{"sha":"2748e1c88078667ba78e3196c33e9a6188007aba","filename":"examples/custom-evm/Cargo.toml","status":"added","additions":18,"deletions":0,"changes":18,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-evm%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-evm%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-evm%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,18 @@\n+[package]\n+name = \"custom-evm\"\n+version = \"0.0.0\"\n+publish = false\n+edition.workspace = true\n+license.workspace = true\n+\n+[dependencies]\n+reth.workspace = true\n+reth-node-api.workspace = true\n+reth-node-core.workspace = true\n+reth-primitives.workspace = true\n+reth-node-ethereum.workspace = true\n+reth-tracing.workspace = true\n+\n+alloy-chains.workspace = true\n+eyre.workspace = true\n+tokio.workspace = true"},{"sha":"ac9324e0ba130ec1772d63623ae83d3134039de6","filename":"examples/custom-evm/src/main.rs","status":"added","additions":147,"deletions":0,"changes":147,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-evm%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-evm%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-evm%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,147 @@\n+//! This example shows how to implement a node with a custom EVM\n+\n+#![warn(unused_crate_dependencies)]\n+\n+use alloy_chains::Chain;\n+use reth::{\n+    builder::{node::NodeTypes, NodeBuilder},\n+    primitives::{\n+        address,\n+        revm_primitives::{CfgEnvWithHandlerCfg, Env, PrecompileResult, TxEnv},\n+        Address, Bytes, U256,\n+    },\n+    revm::{\n+        handler::register::EvmHandler,\n+        precompile::{Precompile, PrecompileSpecId, Precompiles},\n+        Database, Evm, EvmBuilder,\n+    },\n+    tasks::TaskManager,\n+};\n+use reth_node_api::{ConfigureEvm, ConfigureEvmEnv};\n+use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};\n+use reth_node_ethereum::{EthEngineTypes, EthEvmConfig, EthereumNode};\n+use reth_primitives::{ChainSpec, Genesis, Header, Transaction};\n+use reth_tracing::{RethTracer, Tracer};\n+use std::sync::Arc;\n+\n+/// Custom EVM configuration\n+#[derive(Debug, Clone, Copy, Default)]\n+#[non_exhaustive]\n+pub struct MyEvmConfig;\n+\n+impl MyEvmConfig {\n+    /// Sets the precompiles to the EVM handler\n+    ///\n+    /// This will be invoked when the EVM is created via [ConfigureEvm::evm] or\n+    /// [ConfigureEvm::evm_with_inspector]\n+    ///\n+    /// This will use the default mainnet precompiles and add additional precompiles.\n+    pub fn set_precompiles<EXT, DB>(handler: &mut EvmHandler<EXT, DB>)\n+    where\n+        DB: Database,\n+    {\n+        // first we need the evm spec id, which determines the precompiles\n+        let spec_id = handler.cfg.spec_id;\n+\n+        // install the precompiles\n+        handler.pre_execution.load_precompiles = Arc::new(move || {\n+            let mut precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(spec_id)).clone();\n+            precompiles.inner.insert(\n+                address!(\"0000000000000000000000000000000000000999\"),\n+                Precompile::Env(Self::my_precompile),\n+            );\n+            precompiles\n+        });\n+    }\n+\n+    /// A custom precompile that does nothing\n+    fn my_precompile(_data: &Bytes, _gas: u64, _env: &Env) -> PrecompileResult {\n+        Ok((0, Bytes::new()))\n+    }\n+}\n+\n+impl ConfigureEvmEnv for MyEvmConfig {\n+    type TxMeta = ();\n+\n+    fn fill_tx_env<T>(tx_env: &mut TxEnv, transaction: T, sender: Address, meta: Self::TxMeta)\n+    where\n+        T: AsRef<Transaction>,\n+    {\n+        EthEvmConfig::fill_tx_env(tx_env, transaction, sender, meta)\n+    }\n+\n+    fn fill_cfg_env(\n+        cfg_env: &mut CfgEnvWithHandlerCfg,\n+        chain_spec: &ChainSpec,\n+        header: &Header,\n+        total_difficulty: U256,\n+    ) {\n+        EthEvmConfig::fill_cfg_env(cfg_env, chain_spec, header, total_difficulty)\n+    }\n+}\n+\n+impl ConfigureEvm for MyEvmConfig {\n+    fn evm<'a, DB: Database + 'a>(&self, db: DB) -> Evm<'a, (), DB> {\n+        EvmBuilder::default()\n+            .with_db(db)\n+            // add additional precompiles\n+            .append_handler_register(MyEvmConfig::set_precompiles)\n+            .build()\n+    }\n+\n+    fn evm_with_inspector<'a, DB: Database + 'a, I>(&self, db: DB, inspector: I) -> Evm<'a, I, DB> {\n+        EvmBuilder::default()\n+            .with_db(db)\n+            .with_external_context(inspector)\n+            // add additional precompiles\n+            .append_handler_register(MyEvmConfig::set_precompiles)\n+            .build()\n+    }\n+}\n+\n+#[derive(Debug, Clone, Default)]\n+#[non_exhaustive]\n+struct MyCustomNode;\n+\n+/// Configure the node types\n+impl NodeTypes for MyCustomNode {\n+    type Primitives = ();\n+    type Engine = EthEngineTypes;\n+    type Evm = MyEvmConfig;\n+\n+    fn evm_config(&self) -> Self::Evm {\n+        Self::Evm::default()\n+    }\n+}\n+\n+#[tokio::main]\n+async fn main() -> eyre::Result<()> {\n+    let _guard = RethTracer::new().init()?;\n+\n+    let tasks = TaskManager::current();\n+\n+    // create optimism genesis with canyon at block 2\n+    let spec = ChainSpec::builder()\n+        .chain(Chain::mainnet())\n+        .genesis(Genesis::default())\n+        .london_activated()\n+        .paris_activated()\n+        .shanghai_activated()\n+        .cancun_activated()\n+        .build();\n+\n+    let node_config =\n+        NodeConfig::test().with_rpc(RpcServerArgs::default().with_http()).with_chain(spec);\n+\n+    let handle = NodeBuilder::new(node_config)\n+        .testing_node(tasks.executor())\n+        .with_types(MyCustomNode::default())\n+        .with_components(EthereumNode::components())\n+        .launch()\n+        .await\n+        .unwrap();\n+\n+    println!(\"Node started\");\n+\n+    handle.node_exit_future.await\n+}"},{"sha":"d2dc4ba14ad14729eda989bec70ec214efc07ef6","filename":"examples/custom-inspector/Cargo.toml","status":"modified","additions":2,"deletions":2,"changes":4,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-inspector%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-inspector%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-inspector%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -7,6 +7,6 @@ license.workspace = true\n \n [dependencies]\n reth.workspace = true\n+reth-node-ethereum.workspace = true\n clap = { workspace = true, features = [\"derive\"] }\n-futures-util.workspace = true\n-eyre.workspace = true\n\\ No newline at end of file\n+futures-util.workspace = true\n\\ No newline at end of file"},{"sha":"246073df9051a0d3152235685b7f252051f16bdc","filename":"examples/custom-inspector/src/main.rs","status":"modified","additions":70,"deletions":89,"changes":159,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-inspector%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-inspector%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-inspector%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -11,15 +11,11 @@\n #![warn(unused_crate_dependencies)]\n \n use clap::Parser;\n-use futures_util::stream::StreamExt;\n+use futures_util::StreamExt;\n use reth::{\n-    cli::{\n-        components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},\n-        config::RethRpcConfig,\n-        ext::{RethCliExt, RethNodeCommandConfig},\n-        Cli,\n-    },\n-    primitives::{Address, BlockId, IntoRecoveredTransaction},\n+    builder::NodeHandle,\n+    cli::Cli,\n+    primitives::{Address, BlockNumberOrTag, IntoRecoveredTransaction},\n     revm::{\n         inspector_handle_register,\n         interpreter::{Interpreter, OpCode},\n@@ -29,21 +25,79 @@ use reth::{\n         compat::transaction::transaction_to_call_request,\n         eth::{revm_utils::EvmOverrides, EthTransactions},\n     },\n-    tasks::TaskSpawner,\n     transaction_pool::TransactionPool,\n };\n+use reth_node_ethereum::node::EthereumNode;\n use std::collections::HashSet;\n \n fn main() {\n-    Cli::<MyRethCliExt>::parse().run().unwrap();\n-}\n+    Cli::<RethCliTxpoolExt>::parse()\n+        .run(|builder, args| async move {\n+            // launch the node\n+            let NodeHandle { mut node, node_exit_future } =\n+                builder.node(EthereumNode::default()).launch().await?;\n+\n+            let recipients = args.recipients.iter().copied().collect::<HashSet<_>>();\n+\n+            // create a new subscription to pending transactions\n+            let mut pending_transactions = node.pool.new_pending_pool_transactions_listener();\n+\n+            // get an instance of the `trace_` API handler\n+            let eth_api = node.rpc_registry.eth_api();\n+\n+            println!(\"Spawning trace task!\");\n \n-/// The type that tells the reth CLI what extensions to use\n-struct MyRethCliExt;\n+            // Spawn an async block to listen for transactions.\n+            node.task_executor.spawn(Box::pin(async move {\n+                // Waiting for new transactions\n+                while let Some(event) = pending_transactions.next().await {\n+                    let tx = event.transaction;\n+                    println!(\"Transaction received: {tx:?}\");\n+\n+                    if recipients.is_empty() {\n+                        // convert the pool transaction\n+                        let call_request =\n+                            transaction_to_call_request(tx.to_recovered_transaction());\n+\n+                        let result = eth_api\n+                            .spawn_with_call_at(\n+                                call_request,\n+                                BlockNumberOrTag::Latest.into(),\n+                                EvmOverrides::default(),\n+                                move |db, env| {\n+                                    let mut dummy_inspector = DummyInspector::default();\n+                                    {\n+                                        // configure the evm with the custom inspector\n+                                        let mut evm = Evm::builder()\n+                                            .with_db(db)\n+                                            .with_external_context(&mut dummy_inspector)\n+                                            .with_env_with_handler_cfg(env)\n+                                            .append_handler_register(inspector_handle_register)\n+                                            .build();\n+                                        // execute the transaction on a blocking task and await the\n+                                        // inspector result\n+                                        let _ = evm.transact()?;\n+                                    }\n+                                    Ok(dummy_inspector)\n+                                },\n+                            )\n+                            .await;\n+\n+                        if let Ok(ret_val) = result {\n+                            let hash = tx.hash();\n+                            println!(\n+                                \"Inspector result for transaction {}: \\n {}\",\n+                                hash,\n+                                ret_val.ret_val.join(\"\\n\")\n+                            );\n+                        }\n+                    }\n+                }\n+            }));\n \n-impl RethCliExt for MyRethCliExt {\n-    /// This tells the reth CLI to trace addresses via `RethCliTxpoolExt`\n-    type Node = RethCliTxpoolExt;\n+            node_exit_future.await\n+        })\n+        .unwrap();\n }\n \n /// Our custom cli args extension that adds one flag to reth default CLI.\n@@ -74,76 +128,3 @@ where\n         }\n     }\n }\n-\n-impl RethNodeCommandConfig for RethCliTxpoolExt {\n-    /// Sets up a subscription to listen for new pending transactions and traces them.\n-    /// If the transaction is from one of the specified recipients, it will be traced.\n-    /// If no recipients are specified, all transactions will be traced.\n-    fn on_rpc_server_started<Conf, Reth>(\n-        &mut self,\n-        _config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-        _handles: RethRpcServerHandles,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        let recipients = self.recipients.iter().copied().collect::<HashSet<_>>();\n-\n-        // create a new subscription to pending transactions\n-        let mut pending_transactions = components.pool().new_pending_pool_transactions_listener();\n-\n-        let eth_api = rpc_components.registry.eth_api();\n-\n-        println!(\"Spawning trace task!\");\n-        // Spawn an async block to listen for transactions.\n-        components.task_executor().spawn(Box::pin(async move {\n-            // Waiting for new transactions\n-            while let Some(event) = pending_transactions.next().await {\n-                let tx = event.transaction;\n-                println!(\"Transaction received: {tx:?}\");\n-\n-                if recipients.is_empty() {\n-                    // convert the pool transaction\n-                    let call_request = transaction_to_call_request(tx.to_recovered_transaction());\n-\n-                    let result = eth_api\n-                        .spawn_with_call_at(\n-                            call_request,\n-                            BlockId::default(),\n-                            EvmOverrides::default(),\n-                            move |db, env| {\n-                                let mut dummy_inspector = DummyInspector::default();\n-                                {\n-                                    // configure the evm with the custom inspector\n-                                    let mut evm = Evm::builder()\n-                                        .with_db(db)\n-                                        .with_external_context(&mut dummy_inspector)\n-                                        .with_env_with_handler_cfg(env)\n-                                        .append_handler_register(inspector_handle_register)\n-                                        .build();\n-                                    // execute the transaction on a blocking task and await the\n-                                    // inspector result\n-                                    let _ = evm.transact()?;\n-                                }\n-                                Ok(dummy_inspector)\n-                            },\n-                        )\n-                        .await;\n-\n-                    if let Ok(ret_val) = result {\n-                        let hash = tx.hash();\n-                        println!(\n-                            \"Inspector result for transaction {}: \\n {}\",\n-                            hash,\n-                            ret_val.ret_val.join(\"\\n\")\n-                        );\n-                    }\n-                }\n-            }\n-        }));\n-        Ok(())\n-    }\n-}"},{"sha":"761eeaf1b60f36d5a629ce1e6516e225a14ff2a3","filename":"examples/custom-node-components/Cargo.toml","status":"added","additions":16,"deletions":0,"changes":16,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node-components%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node-components%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-node-components%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,16 @@\n+[package]\n+name = \"custom-node-components\"\n+version = \"0.0.0\"\n+publish = false\n+edition.workspace = true\n+license.workspace = true\n+\n+\n+[dependencies]\n+reth.workspace = true\n+reth-node-ethereum.workspace = true\n+reth-transaction-pool.workspace = true\n+reth-tracing.workspace = true\n+\n+\n+eyre.workspace = true"},{"sha":"4459cb71cf119833124fc0e8a57d6cd7443cb5c4","filename":"examples/custom-node-components/src/main.rs","status":"added","additions":104,"deletions":0,"changes":104,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node-components%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node-components%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-node-components%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -0,0 +1,104 @@\n+//! This example shows how to configure custom components for a reth node.\n+\n+#![warn(unused_crate_dependencies)]\n+\n+use reth::{\n+    builder::{components::PoolBuilder, BuilderContext, FullNodeTypes},\n+    cli::Cli,\n+    providers::CanonStateSubscriptions,\n+    transaction_pool::{\n+        blobstore::InMemoryBlobStore, EthTransactionPool, TransactionValidationTaskExecutor,\n+    },\n+};\n+use reth_node_ethereum::EthereumNode;\n+use reth_tracing::tracing::{debug, info};\n+use reth_transaction_pool::PoolConfig;\n+\n+fn main() {\n+    Cli::parse_args()\n+        .run(|builder, _| async move {\n+            let handle = builder\n+                // use the default ethereum node types\n+                .with_types(EthereumNode::default())\n+                // Configure the components of the node\n+                // use default ethereum components but use our custom pool\n+                .with_components(EthereumNode::components().pool(CustomPoolBuilder::default()))\n+                .launch()\n+                .await?;\n+\n+            handle.wait_for_node_exit().await\n+        })\n+        .unwrap();\n+}\n+\n+/// A custom pool builder\n+#[derive(Debug, Clone, Default)]\n+#[non_exhaustive]\n+pub struct CustomPoolBuilder {\n+    /// Use custom pool config\n+    pool_config: PoolConfig,\n+}\n+\n+/// Implement the `PoolBuilder` trait for the custom pool builder\n+///\n+/// This will be used to build the transaction pool and its maintenance tasks during launch.\n+impl<Node> PoolBuilder<Node> for CustomPoolBuilder\n+where\n+    Node: FullNodeTypes,\n+{\n+    type Pool = EthTransactionPool<Node::Provider, InMemoryBlobStore>;\n+\n+    async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {\n+        let data_dir = ctx.data_dir();\n+        let blob_store = InMemoryBlobStore::default();\n+        let validator = TransactionValidationTaskExecutor::eth_builder(ctx.chain_spec())\n+            .with_head_timestamp(ctx.head().timestamp)\n+            .kzg_settings(ctx.kzg_settings()?)\n+            .with_additional_tasks(5)\n+            .build_with_tasks(\n+                ctx.provider().clone(),\n+                ctx.task_executor().clone(),\n+                blob_store.clone(),\n+            );\n+\n+        let transaction_pool =\n+            reth_transaction_pool::Pool::eth_pool(validator, blob_store, self.pool_config);\n+        info!(target: \"reth::cli\", \"Transaction pool initialized\");\n+        let transactions_path = data_dir.txpool_transactions_path();\n+\n+        // spawn txpool maintenance task\n+        {\n+            let pool = transaction_pool.clone();\n+            let chain_events = ctx.provider().canonical_state_stream();\n+            let client = ctx.provider().clone();\n+            let transactions_backup_config =\n+                reth_transaction_pool::maintain::LocalTransactionBackupConfig::with_local_txs_backup(transactions_path);\n+\n+            ctx.task_executor().spawn_critical_with_graceful_shutdown_signal(\n+                \"local transactions backup task\",\n+                |shutdown| {\n+                    reth_transaction_pool::maintain::backup_local_transactions_task(\n+                        shutdown,\n+                        pool.clone(),\n+                        transactions_backup_config,\n+                    )\n+                },\n+            );\n+\n+            // spawn the maintenance task\n+            ctx.task_executor().spawn_critical(\n+                \"txpool maintenance task\",\n+                reth_transaction_pool::maintain::maintain_transaction_pool_future(\n+                    client,\n+                    pool,\n+                    chain_events,\n+                    ctx.task_executor().clone(),\n+                    Default::default(),\n+                ),\n+            );\n+            debug!(target: \"reth::cli\", \"Spawned txpool maintenance task\");\n+        }\n+\n+        Ok(transaction_pool)\n+    }\n+}"},{"sha":"53efdc0a831859b1b9c4388f0e74b80ef4e88806","filename":"examples/custom-node/Cargo.toml","status":"modified","additions":4,"deletions":4,"changes":8,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-node%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,19 +5,19 @@ publish = false\n edition.workspace = true\n license.workspace = true\n \n-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n-\n [dependencies]\n reth.workspace = true\n-reth-rpc-api.workspace = true\n reth-rpc-types.workspace = true\n reth-node-api.workspace = true\n reth-node-core.workspace = true\n reth-primitives.workspace = true\n reth-payload-builder.workspace = true\n+reth-basic-payload-builder.workspace = true\n+reth-ethereum-payload-builder.workspace = true\n+reth-node-ethereum.workspace = true\n+reth-tracing.workspace = true\n \n alloy-chains.workspace = true\n-jsonrpsee.workspace = true\n eyre.workspace = true\n tokio.workspace = true\n thiserror.workspace = true"},{"sha":"ab707802fdd051413c0813c96e40b718af1de695","filename":"examples/custom-node/src/main.rs","status":"modified","additions":190,"deletions":92,"changes":282,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-node%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-node%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -15,25 +15,43 @@\n //! Once traits are implemented and custom types are defined, the [EngineTypes] trait can be\n //! implemented:\n \n+#![warn(unused_crate_dependencies)]\n+\n use alloy_chains::Chain;\n-use jsonrpsee::http_client::HttpClient;\n-use reth::builder::spawn_node;\n+use reth::{\n+    builder::{\n+        components::{ComponentsBuilder, PayloadServiceBuilder},\n+        node::NodeTypes,\n+        BuilderContext, FullNodeTypes, Node, NodeBuilder, PayloadBuilderConfig,\n+    },\n+    primitives::revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg},\n+    providers::{CanonStateSubscriptions, StateProviderFactory},\n+    tasks::TaskManager,\n+    transaction_pool::TransactionPool,\n+};\n+use reth_basic_payload_builder::{\n+    BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig, BuildArguments, BuildOutcome,\n+    PayloadBuilder, PayloadConfig,\n+};\n use reth_node_api::{\n     validate_version_specific_fields, AttributesValidationError, EngineApiMessageVersion,\n     EngineTypes, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes,\n };\n use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};\n-use reth_payload_builder::{EthBuiltPayload, EthPayloadBuilderAttributes};\n-use reth_primitives::{\n-    revm::config::revm_spec_by_timestamp_after_merge,\n-    revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId},\n-    Address, ChainSpec, Genesis, Header, Withdrawals, B256, U256,\n+use reth_node_ethereum::{\n+    node::{EthereumNetworkBuilder, EthereumPoolBuilder},\n+    EthEvmConfig,\n+};\n+use reth_payload_builder::{\n+    error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, PayloadBuilderHandle,\n+    PayloadBuilderService,\n };\n-use reth_rpc_api::{EngineApiClient, EthApiClient};\n+use reth_primitives::{Address, ChainSpec, Genesis, Header, Withdrawals, B256};\n use reth_rpc_types::{\n-    engine::{ForkchoiceState, PayloadAttributes as EthPayloadAttributes, PayloadId},\n+    engine::{PayloadAttributes as EthPayloadAttributes, PayloadId},\n     withdrawal::Withdrawal,\n };\n+use reth_tracing::{RethTracer, Tracer};\n use serde::{Deserialize, Serialize};\n use std::convert::Infallible;\n use thiserror::Error;\n@@ -84,7 +102,7 @@ impl PayloadAttributes for CustomPayloadAttributes {\n     }\n }\n \n-/// Newtype around the payload builder attributes type\n+/// New type around the payload builder attributes type\n #[derive(Clone, Debug, PartialEq, Eq)]\n pub struct CustomPayloadBuilderAttributes(EthPayloadBuilderAttributes);\n \n@@ -123,50 +141,13 @@ impl PayloadBuilderAttributes for CustomPayloadBuilderAttributes {\n     fn withdrawals(&self) -> &Withdrawals {\n         &self.0.withdrawals\n     }\n+\n     fn cfg_and_block_env(\n         &self,\n         chain_spec: &ChainSpec,\n         parent: &Header,\n     ) -> (CfgEnvWithHandlerCfg, BlockEnv) {\n-        // configure evm env based on parent block\n-        let mut cfg = CfgEnv::default();\n-        cfg.chain_id = chain_spec.chain().id();\n-\n-        // ensure we're not missing any timestamp based hardforks\n-        let spec_id = revm_spec_by_timestamp_after_merge(chain_spec, self.timestamp());\n-\n-        // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is\n-        // cancun now, we need to set the excess blob gas to the default value\n-        let blob_excess_gas_and_price = parent\n-            .next_block_excess_blob_gas()\n-            .or_else(|| {\n-                if spec_id == SpecId::CANCUN {\n-                    // default excess blob gas is zero\n-                    Some(0)\n-                } else {\n-                    None\n-                }\n-            })\n-            .map(BlobExcessGasAndPrice::new);\n-\n-        let block_env = BlockEnv {\n-            number: U256::from(parent.number + 1),\n-            coinbase: self.suggested_fee_recipient(),\n-            timestamp: U256::from(self.timestamp()),\n-            difficulty: U256::ZERO,\n-            prevrandao: Some(self.prev_randao()),\n-            gas_limit: U256::from(parent.gas_limit),\n-            // calculate basefee based on parent block's gas usage\n-            basefee: U256::from(\n-                parent\n-                    .next_block_base_fee(chain_spec.base_fee_params(self.timestamp()))\n-                    .unwrap_or_default(),\n-            ),\n-            // calculate excess gas based on parent block's blob gas usage\n-            blob_excess_gas_and_price,\n-        };\n-\n-        (CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env)\n+        self.0.cfg_and_block_env(chain_spec, parent)\n     }\n }\n \n@@ -190,10 +171,156 @@ impl EngineTypes for CustomEngineTypes {\n     }\n }\n \n+#[derive(Debug, Clone, Default)]\n+#[non_exhaustive]\n+struct MyCustomNode;\n+\n+/// Configure the node types\n+impl NodeTypes for MyCustomNode {\n+    type Primitives = ();\n+    // use the custom engine types\n+    type Engine = CustomEngineTypes;\n+    // use the default ethereum EVM config\n+    type Evm = EthEvmConfig;\n+\n+    fn evm_config(&self) -> Self::Evm {\n+        Self::Evm::default()\n+    }\n+}\n+\n+/// Implement the Node trait for the custom node\n+///\n+/// This provides a preset configuration for the node\n+impl<N> Node<N> for MyCustomNode\n+where\n+    N: FullNodeTypes<Engine = CustomEngineTypes>,\n+{\n+    type PoolBuilder = EthereumPoolBuilder;\n+    type NetworkBuilder = EthereumNetworkBuilder;\n+    type PayloadBuilder = CustomPayloadServiceBuilder;\n+\n+    fn components(\n+        self,\n+    ) -> ComponentsBuilder<N, Self::PoolBuilder, Self::PayloadBuilder, Self::NetworkBuilder> {\n+        ComponentsBuilder::default()\n+            .node_types::<N>()\n+            .pool(EthereumPoolBuilder::default())\n+            .payload(CustomPayloadServiceBuilder::default())\n+            .network(EthereumNetworkBuilder::default())\n+    }\n+}\n+\n+/// A custom payload service builder that supports the custom engine types\n+#[derive(Debug, Default, Clone)]\n+#[non_exhaustive]\n+pub struct CustomPayloadServiceBuilder;\n+\n+impl<Node, Pool> PayloadServiceBuilder<Node, Pool> for CustomPayloadServiceBuilder\n+where\n+    Node: FullNodeTypes<Engine = CustomEngineTypes>,\n+    Pool: TransactionPool + Unpin + 'static,\n+{\n+    async fn spawn_payload_service(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> {\n+        let payload_builder = CustomPayloadBuilder::default();\n+        let conf = ctx.payload_builder_config();\n+\n+        let payload_job_config = BasicPayloadJobGeneratorConfig::default()\n+            .interval(conf.interval())\n+            .deadline(conf.deadline())\n+            .max_payload_tasks(conf.max_payload_tasks())\n+            .extradata(conf.extradata_rlp_bytes())\n+            .max_gas_limit(conf.max_gas_limit());\n+\n+        let payload_generator = BasicPayloadJobGenerator::with_builder(\n+            ctx.provider().clone(),\n+            pool,\n+            ctx.task_executor().clone(),\n+            payload_job_config,\n+            ctx.chain_spec(),\n+            payload_builder,\n+        );\n+        let (payload_service, payload_builder) =\n+            PayloadBuilderService::new(payload_generator, ctx.provider().canonical_state_stream());\n+\n+        ctx.task_executor().spawn_critical(\"payload builder service\", Box::pin(payload_service));\n+\n+        Ok(payload_builder)\n+    }\n+}\n+\n+/// The type responsible for building custom payloads\n+#[derive(Debug, Default, Clone)]\n+#[non_exhaustive]\n+pub struct CustomPayloadBuilder;\n+\n+impl<Pool, Client> PayloadBuilder<Pool, Client> for CustomPayloadBuilder\n+where\n+    Client: StateProviderFactory,\n+    Pool: TransactionPool,\n+{\n+    type Attributes = CustomPayloadBuilderAttributes;\n+    type BuiltPayload = EthBuiltPayload;\n+\n+    fn try_build(\n+        &self,\n+        args: BuildArguments<Pool, Client, Self::Attributes, Self::BuiltPayload>,\n+    ) -> Result<BuildOutcome<Self::BuiltPayload>, PayloadBuilderError> {\n+        let BuildArguments { client, pool, cached_reads, config, cancel, best_payload } = args;\n+        let PayloadConfig {\n+            initialized_block_env,\n+            initialized_cfg,\n+            parent_block,\n+            extra_data,\n+            attributes,\n+            chain_spec,\n+        } = config;\n+\n+        // This reuses the default EthereumPayloadBuilder to build the payload\n+        // but any custom logic can be implemented here\n+        reth_ethereum_payload_builder::EthereumPayloadBuilder::default().try_build(BuildArguments {\n+            client,\n+            pool,\n+            cached_reads,\n+            config: PayloadConfig {\n+                initialized_block_env,\n+                initialized_cfg,\n+                parent_block,\n+                extra_data,\n+                attributes: attributes.0,\n+                chain_spec,\n+            },\n+            cancel,\n+            best_payload,\n+        })\n+    }\n+\n+    fn build_empty_payload(\n+        client: &Client,\n+        config: PayloadConfig<Self::Attributes>,\n+    ) -> Result<Self::BuiltPayload, PayloadBuilderError> {\n+        let PayloadConfig {\n+            initialized_block_env,\n+            initialized_cfg,\n+            parent_block,\n+            extra_data,\n+            attributes,\n+            chain_spec,\n+        } = config;\n+        <reth_ethereum_payload_builder::EthereumPayloadBuilder  as PayloadBuilder<Pool,Client>>  ::build_empty_payload(client,\n+                                                                                                                       PayloadConfig { initialized_block_env, initialized_cfg, parent_block, extra_data, attributes: attributes.0, chain_spec }\n+        )\n+    }\n+}\n+\n #[tokio::main]\n async fn main() -> eyre::Result<()> {\n-    // this launches a test node with http\n-    let rpc_args = RpcServerArgs::default().with_http();\n+    let _guard = RethTracer::new().init()?;\n+\n+    let tasks = TaskManager::current();\n \n     // create optimism genesis with canyon at block 2\n     let spec = ChainSpec::builder()\n@@ -204,46 +331,17 @@ async fn main() -> eyre::Result<()> {\n         .shanghai_activated()\n         .build();\n \n-    let genesis_hash = spec.genesis_hash();\n-\n     // create node config\n-    let node_config = NodeConfig::test().with_rpc(rpc_args).with_chain(spec);\n-\n-    let (handle, _manager) = spawn_node(node_config).await.unwrap();\n-\n-    // call a function on the node\n-    let client = handle.rpc_server_handles().auth.http_client();\n-    let block_number = client.block_number().await.unwrap();\n-\n-    // it should be zero, since this is an ephemeral test node\n-    assert_eq!(block_number, U256::ZERO);\n-\n-    // call the engine_forkchoiceUpdated function with payload attributes\n-    let forkchoice_state = ForkchoiceState {\n-        head_block_hash: genesis_hash,\n-        safe_block_hash: genesis_hash,\n-        finalized_block_hash: genesis_hash,\n-    };\n-\n-    let payload_attributes = CustomPayloadAttributes {\n-        inner: EthPayloadAttributes {\n-            timestamp: 1,\n-            prev_randao: Default::default(),\n-            suggested_fee_recipient: Default::default(),\n-            withdrawals: Some(vec![]),\n-            parent_beacon_block_root: None,\n-        },\n-        custom: 42,\n-    };\n-\n-    // call the engine_forkchoiceUpdated function with payload attributes\n-    let res = <HttpClient as EngineApiClient<CustomEngineTypes>>::fork_choice_updated_v2(\n-        &client,\n-        forkchoice_state,\n-        Some(payload_attributes),\n-    )\n-    .await;\n-    assert!(res.is_ok());\n-\n-    Ok(())\n+    let node_config =\n+        NodeConfig::test().with_rpc(RpcServerArgs::default().with_http()).with_chain(spec);\n+\n+    let handle = NodeBuilder::new(node_config)\n+        .testing_node(tasks.executor())\n+        .launch_node(MyCustomNode::default())\n+        .await\n+        .unwrap();\n+\n+    println!(\"Node started\");\n+\n+    handle.node_exit_future.await\n }"},{"sha":"58fa775271c62ca01393d1689468e67616cc304e","filename":"examples/custom-payload-builder/Cargo.toml","status":"modified","additions":3,"deletions":5,"changes":8,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-payload-builder%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-payload-builder%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-payload-builder%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -5,17 +5,15 @@ publish = false\n edition.workspace = true\n license.workspace = true\n \n-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n-\n [dependencies]\n reth.workspace = true\n reth-primitives.workspace = true\n reth-node-api.workspace = true\n reth-basic-payload-builder.workspace = true\n reth-payload-builder.workspace = true\n+reth-node-ethereum.workspace = true\n+reth-ethereum-payload-builder.workspace = true\n \n tracing.workspace = true\n-clap = { workspace = true, features = [\"derive\"] }\n futures-util.workspace = true\n-eyre.workspace = true\n-tokio.workspace = true\n\\ No newline at end of file\n+eyre.workspace = true\n\\ No newline at end of file"},{"sha":"67a0bc223d0d9ac336b716169879539c96436862","filename":"examples/custom-payload-builder/src/main.rs","status":"modified","additions":46,"deletions":49,"changes":95,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-payload-builder%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Fcustom-payload-builder%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Fcustom-payload-builder%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -8,58 +8,40 @@\n //! ```\n //!\n //! This launch the regular reth node overriding the engine api payload builder with our custom.\n-use clap::Parser;\n+\n+#![warn(unused_crate_dependencies)]\n+\n use generator::EmptyBlockPayloadJobGenerator;\n use reth::{\n-    cli::{\n-        components::RethNodeComponents,\n-        config::PayloadBuilderConfig,\n-        ext::{NoArgsCliExt, RethNodeCommandConfig},\n-        Cli,\n-    },\n+    builder::{components::PayloadServiceBuilder, node::FullNodeTypes, BuilderContext},\n+    cli::{config::PayloadBuilderConfig, Cli},\n     payload::PayloadBuilderHandle,\n     providers::CanonStateSubscriptions,\n-    tasks::TaskSpawner,\n+    transaction_pool::TransactionPool,\n };\n-use reth_basic_payload_builder::{BasicPayloadJobGeneratorConfig, PayloadBuilder};\n-use reth_node_api::EngineTypes;\n+use reth_basic_payload_builder::BasicPayloadJobGeneratorConfig;\n+use reth_node_ethereum::{EthEngineTypes, EthereumNode};\n use reth_payload_builder::PayloadBuilderService;\n \n pub mod generator;\n pub mod job;\n \n-fn main() {\n-    Cli::<NoArgsCliExt<MyCustomBuilder>>::parse()\n-        .with_node_extension(MyCustomBuilder::default())\n-        .run()\n-        .unwrap();\n-}\n-\n-/// Our custom cli args extension that adds one flag to reth default CLI.\n #[derive(Debug, Clone, Copy, Default)]\n #[non_exhaustive]\n-struct MyCustomBuilder;\n+pub struct CustomPayloadBuilder;\n \n-impl RethNodeCommandConfig for MyCustomBuilder {\n-    fn spawn_payload_builder_service<Conf, Reth, Builder, Engine>(\n-        &mut self,\n-        conf: &Conf,\n-        components: &Reth,\n-        payload_builder: Builder,\n-    ) -> eyre::Result<PayloadBuilderHandle<Engine>>\n-    where\n-        Conf: PayloadBuilderConfig,\n-        Reth: RethNodeComponents,\n-        Engine: EngineTypes + 'static,\n-        Builder: PayloadBuilder<\n-                Reth::Pool,\n-                Reth::Provider,\n-                Attributes = Engine::PayloadBuilderAttributes,\n-                BuiltPayload = Engine::BuiltPayload,\n-            > + Unpin\n-            + 'static,\n-    {\n+impl<Node, Pool> PayloadServiceBuilder<Node, Pool> for CustomPayloadBuilder\n+where\n+    Node: FullNodeTypes<Engine = EthEngineTypes>,\n+    Pool: TransactionPool + Unpin + 'static,\n+{\n+    async fn spawn_payload_service(\n+        self,\n+        ctx: &BuilderContext<Node>,\n+        pool: Pool,\n+    ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> {\n         tracing::info!(\"Spawning a custom payload builder\");\n+        let conf = ctx.payload_builder_config();\n \n         let payload_job_config = BasicPayloadJobGeneratorConfig::default()\n             .interval(conf.interval())\n@@ -69,23 +51,38 @@ impl RethNodeCommandConfig for MyCustomBuilder {\n             .max_gas_limit(conf.max_gas_limit());\n \n         let payload_generator = EmptyBlockPayloadJobGenerator::with_builder(\n-            components.provider(),\n-            components.pool(),\n-            components.task_executor(),\n+            ctx.provider().clone(),\n+            pool,\n+            ctx.task_executor().clone(),\n             payload_job_config,\n-            components.chain_spec().clone(),\n-            payload_builder,\n+            ctx.chain_spec().clone(),\n+            reth_ethereum_payload_builder::EthereumPayloadBuilder::default(),\n         );\n \n-        let (payload_service, payload_builder) = PayloadBuilderService::new(\n-            payload_generator,\n-            components.events().canonical_state_stream(),\n-        );\n+        let (payload_service, payload_builder) =\n+            PayloadBuilderService::new(payload_generator, ctx.provider().canonical_state_stream());\n \n-        components\n-            .task_executor()\n+        ctx.task_executor()\n             .spawn_critical(\"custom payload builder service\", Box::pin(payload_service));\n \n         Ok(payload_builder)\n     }\n }\n+\n+fn main() {\n+    Cli::parse_args()\n+        .run(|builder, _| async move {\n+            let handle = builder\n+                .with_types(EthereumNode::default())\n+                // Configure the components of the node\n+                // use default ethereum components but use our custom payload builder\n+                .with_components(\n+                    EthereumNode::components().payload(CustomPayloadBuilder::default()),\n+                )\n+                .launch()\n+                .await?;\n+\n+            handle.wait_for_node_exit().await\n+        })\n+        .unwrap();\n+}"},{"sha":"3f681c2defff8d6b3a88ce87f3253247838023d0","filename":"examples/trace-transaction-cli/Cargo.toml","status":"modified","additions":2,"deletions":6,"changes":8,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Ftrace-transaction-cli%2FCargo.toml","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Ftrace-transaction-cli%2FCargo.toml","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Ftrace-transaction-cli%2FCargo.toml?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -7,10 +7,6 @@ license.workspace = true\n \n [dependencies]\n reth.workspace = true\n+reth-node-ethereum.workspace = true\n clap = { workspace = true, features = [\"derive\"] }\n-jsonrpsee = { workspace = true, features = [\"server\", \"macros\"] }\n-futures-util.workspace = true\n-eyre.workspace = true\n-\n-[dev-dependencies]\n-tokio.workspace = true\n\\ No newline at end of file\n+futures-util.workspace = true\n\\ No newline at end of file"},{"sha":"8f06ac8a39708351fcc93366ea7979d9eb5ee7c5","filename":"examples/trace-transaction-cli/src/main.rs","status":"modified","additions":44,"deletions":61,"changes":105,"blob_url":"https://github.com/paradigmxyz/reth/blob/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Ftrace-transaction-cli%2Fsrc%2Fmain.rs","raw_url":"https://github.com/paradigmxyz/reth/raw/43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a/examples%2Ftrace-transaction-cli%2Fsrc%2Fmain.rs","contents_url":"https://api.github.com/repos/paradigmxyz/reth/contents/examples%2Ftrace-transaction-cli%2Fsrc%2Fmain.rs?ref=43c2c6c36af704e8a7d7bfa4c551e96d346b1a6a","patch":"@@ -8,35 +8,65 @@\n //!\n //! If no recipients are specified, all transactions will be traced.\n \n+#![warn(unused_crate_dependencies)]\n+\n use clap::Parser;\n use futures_util::StreamExt;\n use reth::{\n-    cli::{\n-        components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},\n-        config::RethRpcConfig,\n-        ext::{RethCliExt, RethNodeCommandConfig},\n-        Cli,\n-    },\n+    builder::NodeHandle,\n+    cli::Cli,\n     primitives::{Address, IntoRecoveredTransaction},\n     rpc::{\n         compat::transaction::transaction_to_call_request,\n         types::trace::{parity::TraceType, tracerequest::TraceCallRequest},\n     },\n-    tasks::TaskSpawner,\n     transaction_pool::TransactionPool,\n };\n+use reth_node_ethereum::node::EthereumNode;\n use std::collections::HashSet;\n \n fn main() {\n-    Cli::<MyRethCliExt>::parse().run().unwrap();\n-}\n+    Cli::<RethCliTxpoolExt>::parse()\n+        .run(|builder, args| async move {\n+            // launch the node\n+            let NodeHandle { mut node, node_exit_future } =\n+                builder.node(EthereumNode::default()).launch().await?;\n+\n+            let recipients = args.recipients.iter().copied().collect::<HashSet<_>>();\n+\n+            // create a new subscription to pending transactions\n+            let mut pending_transactions = node.pool.new_pending_pool_transactions_listener();\n \n-/// The type that tells the reth CLI what extensions to use\n-struct MyRethCliExt;\n+            // get an instance of the `trace_` API handler\n+            let traceapi = node.rpc_registry.trace_api();\n+\n+            println!(\"Spawning trace task!\");\n+            // Spawn an async block to listen for transactions.\n+            node.task_executor.spawn(Box::pin(async move {\n+                // Waiting for new transactions\n+                while let Some(event) = pending_transactions.next().await {\n+                    let tx = event.transaction;\n+                    println!(\"Transaction received: {tx:?}\");\n+\n+                    if let Some(tx_recipient_address) = tx.to() {\n+                        if recipients.is_empty() || recipients.contains(&tx_recipient_address) {\n+                            // trace the transaction with `trace_call`\n+                            let callrequest =\n+                                transaction_to_call_request(tx.to_recovered_transaction());\n+                            let tracerequest = TraceCallRequest::new(callrequest)\n+                                .with_trace_type(TraceType::Trace);\n+                            if let Ok(trace_result) = traceapi.trace_call(tracerequest).await {\n+                                let hash = tx.hash();\n+                                println!(\"trace result for transaction {hash}: {trace_result:?}\");\n+                            }\n+                        }\n+                    }\n+                }\n+            }));\n \n-impl RethCliExt for MyRethCliExt {\n-    /// This tells the reth CLI to trace addresses via `RethCliTxpoolExt`\n-    type Node = RethCliTxpoolExt;\n+            node_exit_future.await\n+        })\n+        .unwrap();\n }\n \n /// Our custom cli args extension that adds one flag to reth default CLI.\n@@ -46,50 +76,3 @@ struct RethCliTxpoolExt {\n     #[arg(long, value_delimiter = ',')]\n     pub recipients: Vec<Address>,\n }\n-\n-impl RethNodeCommandConfig for RethCliTxpoolExt {\n-    fn on_rpc_server_started<Conf, Reth>(\n-        &mut self,\n-        _config: &Conf,\n-        components: &Reth,\n-        rpc_components: RethRpcComponents<'_, Reth>,\n-        _handles: RethRpcServerHandles,\n-    ) -> eyre::Result<()>\n-    where\n-        Conf: RethRpcConfig,\n-        Reth: RethNodeComponents,\n-    {\n-        let recipients = self.recipients.iter().copied().collect::<HashSet<_>>();\n-\n-        // create a new subscription to pending transactions\n-        let mut pending_transactions = components.pool().new_pending_pool_transactions_listener();\n-\n-        // get an instance of the `trace_` API handler\n-        let traceapi = rpc_components.registry.trace_api();\n-\n-        println!(\"Spawning trace task!\");\n-        // Spawn an async block to listen for transactions.\n-        components.task_executor().spawn(Box::pin(async move {\n-            // Waiting for new transactions\n-            while let Some(event) = pending_transactions.next().await {\n-                let tx = event.transaction;\n-                println!(\"Transaction received: {tx:?}\");\n-\n-                if let Some(tx_recipient_address) = tx.to() {\n-                    if recipients.is_empty() || recipients.contains(&tx_recipient_address) {\n-                        // trace the transaction with `trace_call`\n-                        let callrequest =\n-                            transaction_to_call_request(tx.to_recovered_transaction());\n-                        let tracerequest =\n-                            TraceCallRequest::new(callrequest).with_trace_type(TraceType::Trace);\n-                        if let Ok(trace_result) = traceapi.trace_call(tracerequest).await {\n-                            let hash = tx.hash();\n-                            println!(\"trace result for transaction {hash}: {trace_result:?}\");\n-                        }\n-                    }\n-                }\n-            }\n-        }));\n-        Ok(())\n-    }\n-}"}]}