diff --git a/core/error.go b/core/error.go index e6e6ba2f9..7aa14a9a5 100644 --- a/core/error.go +++ b/core/error.go @@ -107,4 +107,7 @@ var ( // ErrBlobTxCreate is returned if a blob transaction has no explicit to field. ErrBlobTxCreate = errors.New("blob transaction of type create") + + // ErrTxReverted is returned if a transaction is reverted. + ErrTxReverted = errors.New("transaction reverted") ) diff --git a/eth/tracers/live/noop.go b/eth/tracers/live/noop.go index 7433c2884..3476eaf5b 100644 --- a/eth/tracers/live/noop.go +++ b/eth/tracers/live/noop.go @@ -60,13 +60,12 @@ func (t *noop) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from comm } func (t *noop) OnTxEnd(receipt *types.Receipt, err error) { -} -func (t *noop) OnBlockStart(ev tracing.BlockEvent) { } -func (t *noop) OnBlockEnd(err error) { -} +func (t *noop) OnBlockStart(ev tracing.BlockEvent) {} + +func (t *noop) OnBlockEnd(err error) {} func (t *noop) OnSkippedBlock(ev tracing.BlockEvent) {} diff --git a/go.mod b/go.mod index 513828ed8..82a89ef4a 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,11 @@ module github.com/ethereum/go-ethereum go 1.21 require ( - buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.2 - buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240723183210-193b02425a52.2 - buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240723183210-d00b2a17ea5b.2 - buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240723183210-414756da3320.2 + buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-bf2928746fde.2 + buf.build/gen/go/astria/execution-apis/grpc/go v1.5.1-00000000000000-cdc3a35f6a0c.1 + buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240801092317-cdc3a35f6a0c.2 + buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240807170122-b074164339d1.2 + buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240807170122-24ff5bcd4581.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 github.com/Microsoft/go-winio v0.6.1 github.com/VictoriaMetrics/fastcache v1.12.1 @@ -72,21 +73,20 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.22.0 + golang.org/x/crypto v0.24.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.19.0 - golang.org/x/text v0.14.0 + golang.org/x/sys v0.21.0 + golang.org/x/text v0.16.0 golang.org/x/time v0.5.0 - golang.org/x/tools v0.20.0 - google.golang.org/grpc v1.64.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d + google.golang.org/grpc v1.64.1 google.golang.org/protobuf v1.34.2 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - buf.build/gen/go/astria/protocol-apis/grpc/go v1.4.0-00000000000000-71710707f61c.2 // indirect - buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240723183210-71710707f61c.2 // indirect + buf.build/gen/go/astria/composer-apis/grpc/go v1.4.0-20240528191859-5569d2ee7204.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/DataDog/zstd v1.4.5 // indirect @@ -151,7 +151,7 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 1ae85d46e..fe8debc82 100644 --- a/go.sum +++ b/go.sum @@ -1,41 +1,31 @@ -buf.build/gen/go/astria/execution-apis/grpc/go v1.3.0-20240627184145-202c666b5a8a.3 h1:NXiXUrU7Rngg7JCgjT1l3T3Z6fyrG9YHUlM88BP2JYg= -buf.build/gen/go/astria/execution-apis/grpc/go v1.3.0-20240627184145-202c666b5a8a.3/go.mod h1:Yy6i/mtJjqrY/fXasQDfUzpwrORpGovaryn800efci8= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-00000000000000-193b02425a52.2 h1:Ii/aTj24isoIZMXzMloxu2F14YCpyeK+Ea1hZ2lacK0= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-00000000000000-193b02425a52.2/go.mod h1:tahjbGWs++LfbilVhcqy1Z+j5DDudIFS/asULbpOK7Q= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.1 h1:hYCnNcMBgnEa6XLAMgGD0cZXoulA1Dmn5xi6cERVqZA= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.1/go.mod h1:SFzpkHZaY4sEyrJ5vSwZU6XdPo1ntBDKXtt75T26dac= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.2 h1:AQF3kJYwmVTPQjKNco4rVEXuzSIGbX41uVTB+y/f6qw= -buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.2/go.mod h1:uh6mpUnlm1fLFVIyTxoWO6ZI9tXw1NvOoVwU7GbKd0Y= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.0-20240627184145-202c666b5a8a.1/go.mod h1:wlbx8NZwEyHsptYNr9xVITSgvO+0b/wWIMwVglYk3fs= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.1-20240627184145-202c666b5a8a.1/go.mod h1:lBkx3jiHbz6XM0FAkbQEmUFNifgc4x7oi9LuOK/HDbg= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-00000000000000-193b02425a52.2 h1:+8TaSw1/U7mXxVxCoLFVXSGGb5taFcb4ySOs3O8PiyI= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-00000000000000-193b02425a52.2/go.mod h1:M33M+2vbkmDV+hzuRAZKYbStTkC0/ygngsuSCVkeAsk= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240627184145-202c666b5a8a.2 h1:IYFQwWxQXFovUY/kMnXWaQJ8KJ5uuLOBE0ks2II254c= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240627184145-202c666b5a8a.2/go.mod h1:czHASkeeVmYV4IC0uo9qWDQ0dmEJeC6LfgYWBwSSREI= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240723183210-193b02425a52.2 h1:Y6cGjtxas4M7MpOJWo6vJ8mlUb5GJxrcqvQG69y1U6c= -buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240723183210-193b02425a52.2/go.mod h1:M33M+2vbkmDV+hzuRAZKYbStTkC0/ygngsuSCVkeAsk= -buf.build/gen/go/astria/primitives/grpc/go v1.3.0-20240626163506-691883836b9e.3/go.mod h1:Zpw9bPoLPVG42SwmXIVuhTJcpLDwsAlAEfcWGP5g43g= -buf.build/gen/go/astria/primitives/grpc/go v1.4.0-20240626163506-691883836b9e.1/go.mod h1:VU1xcDnHOU7++vCZHJzilQGWAd4m1SWTBYKuo4qx/cg= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.0-20240626163506-691883836b9e.1/go.mod h1:t7VCP+ORGGLNXUOwi6T6h99GntTUT7bWzK6BQa/uTbA= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.1-20240626163506-691883836b9e.1/go.mod h1:pkz/GfhAgZSnDxyZ5bmGUzk6iQNAvyW72pYPkqb7Pbk= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2 h1:bCHvCYyvhCPWGc3tpl164ONADbH+nKPSc6KhOWb9tfk= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240723183210-d00b2a17ea5b.2 h1:t/+xJg4+o51+athvyaAm1Y0+cUqIksGcvRPtQhQLecA= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240723183210-d00b2a17ea5b.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= -buf.build/gen/go/astria/protocol-apis/grpc/go v1.4.0-00000000000000-71710707f61c.2 h1:vTrgoAC11YuG4mNl60LdpBrq8bvXE7wz/mZAq/mJM6o= -buf.build/gen/go/astria/protocol-apis/grpc/go v1.4.0-00000000000000-71710707f61c.2/go.mod h1:zp7gcM2FC51ms15hmqjSvl0u0dqdewRk9sbcjLLcP9M= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-00000000000000-71710707f61c.2 h1:0yrBa0INyNxxrS8F8EkDPNP9deg7C0PQqDxSYTRJqH8= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-00000000000000-71710707f61c.2/go.mod h1:qixBDfshysfHPFV2sbY/GXrQ1t9ZsWDV9FwHCak2Qfs= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240723183210-71710707f61c.2 h1:wo28fih7tGzPCNmlVerD6dATjdSFq4ESjBjt9n6XR5M= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240723183210-71710707f61c.2/go.mod h1:qixBDfshysfHPFV2sbY/GXrQ1t9ZsWDV9FwHCak2Qfs= -buf.build/gen/go/astria/sequencerblock-apis/grpc/go v1.3.0-20240627184145-00f432997496.3/go.mod h1:yfnROiGt3TjHXrSHhatAcpXSdzs9WBcS2536pi5lGBQ= -buf.build/gen/go/astria/sequencerblock-apis/grpc/go v1.4.0-20240627184145-00f432997496.1/go.mod h1:viF0ZoRvyO5qpIZb1wB3aBBt9WWKOg5x5t6AFKKuKQU= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.0-20240627184145-00f432997496.1/go.mod h1:qct0qusz8ErM7XwIwAL1fWCIbyjOnlKGUNJwnURUhD8= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.1-20240627184145-00f432997496.1/go.mod h1:KkZ92tBsbbl5HTuN/AbQLkW2ALXsaV5MsEU9PPy/n9c= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240627184145-00f432997496.2 h1:s349kECGqPwCKQ1q09lqBR6782/0zDqDez+FEM5PT0s= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240627184145-00f432997496.2/go.mod h1:NEZbII2+dhqPXaQqMYN8ziELoYQgp7hbDFv5Oc45EZU= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240723183210-414756da3320.2 h1:ENOSXmogo70t5AsSSvnOrt0iQQxwWNOA2xaJIb4OgsY= -buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240723183210-414756da3320.2/go.mod h1:v8vBYbyVlLKElP5ce4JYq8bCo9oNbETvnXucDghgyQ8= +buf.build/gen/go/astria/composer-apis/grpc/go v1.4.0-20240528191859-5569d2ee7204.1/go.mod h1:BC9gY2q0GQhCY3tB/x8yNcNvCFmexFirVBdk9h6pxA8= +buf.build/gen/go/astria/composer-apis/grpc/go v1.5.1-00000000000000-d6bc79e686d1.1 h1:st2GOgCPeP9oBLHZcoI6NLCXasqxI+mdd4PvHkQSmHI= +buf.build/gen/go/astria/composer-apis/grpc/go v1.5.1-00000000000000-d6bc79e686d1.1/go.mod h1:1kIfRp599u8mm0JDy2+IWrPOIpnoUVgDohefELVZH6Q= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.1-20240528191859-5569d2ee7204.1/go.mod h1:uOq/7XZCsgthEafUf1rQ1sy3eS1u3zrDSreEoVVT7Kg= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-2eb0388d467b.2 h1:OWpZ77kM5l63BW7UPsNsfd+gpxgkGJ9c7ECYvq6piLc= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-2eb0388d467b.2/go.mod h1:b2EanWNetNpLiN4uCAUAOczwjGP6cxK8qs3Da3+2Vmg= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-75f8c1da20ac.2 h1:i8ziv/0OoAYr5JuHHROMLkGszb/ucAf3E8K00DoUGm4= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-75f8c1da20ac.2/go.mod h1:b2EanWNetNpLiN4uCAUAOczwjGP6cxK8qs3Da3+2Vmg= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-b8b0a7e37fa2.2 h1:2ektaygWFz5FIEHtkAxsiUZk3TZPWoZAqDjFI8V7vL4= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-b8b0a7e37fa2.2/go.mod h1:vrjomDuiv4T+/yZ/iqIjT6E5NXrBmSCR1yKMRZ8iwlU= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-bf2928746fde.2 h1:7sfeowvm8vSQ+wpKB8ZU3E6GzaV3A+prEwC1DBtY9Ho= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-bf2928746fde.2/go.mod h1:b2EanWNetNpLiN4uCAUAOczwjGP6cxK8qs3Da3+2Vmg= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-f4929f050ad6.2 h1:PQgxFtnE65sbyKRpbMMZHBn2cMBdRHz2Ux7xnGLZuaM= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-f4929f050ad6.2/go.mod h1:b2EanWNetNpLiN4uCAUAOczwjGP6cxK8qs3Da3+2Vmg= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-20240811182651-d6bc79e686d1.2 h1:j94s5dtD9ieJohIObdgt0NvF9UocrnLGAe/2QAQHAFo= +buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-20240811182651-d6bc79e686d1.2/go.mod h1:b2EanWNetNpLiN4uCAUAOczwjGP6cxK8qs3Da3+2Vmg= +buf.build/gen/go/astria/execution-apis/grpc/go v1.5.1-00000000000000-cdc3a35f6a0c.1 h1:/9SoFuKGYYb3XtPxTsPsn3vPY3WkpiIn6UisZF3TJMQ= +buf.build/gen/go/astria/execution-apis/grpc/go v1.5.1-00000000000000-cdc3a35f6a0c.1/go.mod h1:pXISQNa1zGM905/v0nXCPkMZwrEIk+5AmgEs+cTPFCQ= +buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240801092317-cdc3a35f6a0c.2 h1:/4vRNkmKQ6mfzbQpjX5gsAy+jX/Sa95XTvoz3Cr05KA= +buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240801092317-cdc3a35f6a0c.2/go.mod h1:KVuELHO13ERiTsogomrb9+O4lb8s8QlLcix1nArjdrI= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240801092317-1af140bbf6af.2 h1:jVRnwdYnEuCMZVT8WE4MF6j8cdmMzjLO2N1FBrGVv5E= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240801092317-1af140bbf6af.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240807170122-b074164339d1.2 h1:NAgPX0n2M6R16efrxG9U+M128cl0jwIQl+bV3lQH3qg= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240807170122-b074164339d1.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= +buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240801092317-547455022126.2 h1:QKl4FPcbNiGmnWDeG/bIAOzmb93rydMA2Cl1motkgAw= +buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240801092317-547455022126.2/go.mod h1:mohUSyi2UmALXDaJlA1CqHwhaJ84bZHnt09ydfnDsHs= +buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240807170122-24ff5bcd4581.2 h1:6Gt46eV9JveAVi8caJA8iYZUgfzjie8N7rpv3HN6LXg= +buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240807170122-24ff5bcd4581.2/go.mod h1:SB8o8Y631Su8YhDbekqpRn7Y3flTuKP2CdqcmKMBwy0= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -1903,8 +1893,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2041,8 +2031,8 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2208,8 +2198,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -2247,8 +2237,9 @@ golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2326,8 +2317,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2336,7 +2327,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -2660,8 +2650,8 @@ google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSs google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.61.2/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2681,7 +2671,6 @@ google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/grpc/execution/server.go b/grpc/execution/server.go index 773b006dc..8c77114d9 100644 --- a/grpc/execution/server.go +++ b/grpc/execution/server.go @@ -5,6 +5,9 @@ package execution import ( + composerv1alpha1 "buf.build/gen/go/astria/composer-apis/protocolbuffers/go/astria/composer/v1alpha1" + sequencerblockv1alpha1 "buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go/astria/sequencerblock/v1alpha1" + "bytes" "context" "crypto/sha256" "errors" @@ -222,11 +225,45 @@ func protoU128ToBigInt(u128 *primitivev1.Uint128) *big.Int { return lo.Add(lo, hi) } +func unbundleBuilderBundlePacket( + builderBundlePacket *composerv1alpha1.BuilderBundlePacket, + parentHash []byte, + height uint64, + bridgeAddresses map[string]*params.AstriaBridgeAddressConfig, + bridgeAllowedAssets map[string]struct{}, + bridgeSenderAddress common.Address, +) (types.Transactions, error) { + if builderBundlePacket == nil { + return types.Transactions{}, nil + } + + builderBundle := builderBundlePacket.GetBundle() + if bytes.Compare(builderBundle.GetParentHash(), parentHash) != 0 { + log.Error("parent hash does not match parent hash of the block", "parentHash", common.BytesToHash(parentHash).Hex(), "bundleParentHash", common.BytesToHash(builderBundlePacket.GetBundle().GetParentHash()).Hex()) + return types.Transactions{}, nil + } + + // TODO - bundle signature verification + + ethTxs := types.Transactions{} + for _, tx := range builderBundlePacket.GetBundle().GetTransactions() { + ethTx, err := validateAndUnmarshalTx(height, tx, bridgeAddresses, bridgeAllowedAssets, bridgeSenderAddress) + if err != nil { + return nil, err + } + + ethTxs = append(ethTxs, ethTx) + } + + return ethTxs, nil +} + // ExecuteBlock drives deterministic derivation of a rollup block from sequencer // block data -func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *astriaPb.ExecuteBlockRequest) (*astriaPb.Block, error) { - log.Debug("ExecuteBlock called", "prevBlockHash", common.BytesToHash(req.PrevBlockHash), "tx_count", len(req.Transactions), "timestamp", req.Timestamp) +func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *astriaPb.ExecuteBlockRequest) (*astriaPb.ExecuteBlockResponse, error) { + log.Info("Trusted Builder ExecuteBlock called", "prevBlockHash", common.BytesToHash(req.PrevBlockHash), "tx_count", len(req.Transactions), "timestamp", req.Timestamp) executeBlockRequestCount.Inc(1) + log.Info("Mode is set to", "simulateOnly", req.GetSimulateOnly()) s.blockExecutionLock.Lock() defer s.blockExecutionLock.Unlock() @@ -248,18 +285,34 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req * // the height that this block will be at height := s.bc.CurrentBlock().Number.Uint64() + 1 - txsToProcess := types.Transactions{} - for _, tx := range req.Transactions { - unmarshalledTx, err := validateAndUnmarshalSequencerTx(height, tx, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress) - if err != nil { - log.Debug("failed to validate sequencer tx, ignoring", "tx", tx, "err", err) - continue - } - txsToProcess = append(txsToProcess, unmarshalledTx) + log.Info("Extracting builder bundle and other txs") + builderBundlePacket, ethTxs, depositTxMapping, err := extractBuilderBundleAndTxs(req.Transactions, height, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress) + if err != nil { + log.Error("failed to extract builder bundle and txs", "err", err) + return nil, status.Error(codes.InvalidArgument, "Could not extract builder bundle and txs") + } + if req.GetSimulateOnly() && builderBundlePacket != nil { + return nil, status.Error(codes.InvalidArgument, "bundle simulation is not supported for builder bundle packets") + } + if builderBundlePacket == nil { + log.Info("No builder bundle packet found") + } else { + log.Info("Builder bundle packet found") + log.Info("Unbundling the builder bundle packet", "simulateOnly", req.GetSimulateOnly()) + } + + tobTxs, err := unbundleBuilderBundlePacket(builderBundlePacket, req.PrevBlockHash, height, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress) + if err != nil { + log.Error("failed to unbundle builder bundle packet", "err", err) + return nil, status.Error(codes.InvalidArgument, "Could not unbundle builder bundle packet") + } + if builderBundlePacket != nil { + log.Info("Unbundled the builder bundle packet", "tx_count", len(tobTxs)) } - // This set of ordered TXs on the TxPool is has been configured to be used by - // the Miner when building a payload. + txsToProcess := append(tobTxs, ethTxs...) + log.Info("Total txs to process", "tx_count", len(txsToProcess)) + s.eth.TxPool().SetAstriaOrdered(txsToProcess) // Build a payload to add to the chain @@ -269,29 +322,81 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req * Random: common.Hash{}, FeeRecipient: s.nextFeeRecipient, } + log.Info("Building payload") payload, err := s.eth.Miner().BuildPayload(payloadAttributes) if err != nil { log.Error("failed to build payload", "err", err) return nil, status.Error(codes.InvalidArgument, "Could not build block with provided txs") } + log.Info("Built payload!") // call blockchain.InsertChain to actually execute and write the blocks to // state + log.Info("Extracting block out of payload!") block, err := engine.ExecutableDataToBlock(*payload.Resolve().ExecutionPayload, nil, nil) if err != nil { log.Error("failed to convert executable data to block", err) return nil, status.Error(codes.Internal, "failed to execute block") } - err = s.bc.InsertBlockWithoutSetHead(block) - if err != nil { - log.Error("failed to insert block to chain", "hash", block.Hash(), "prevHash", req.PrevBlockHash, "err", err) - return nil, status.Error(codes.Internal, "failed to insert block to chain") + log.Info("Extracted block out of payload!") + + log.Info("Building included_transactions list by removing txs which are in the list of AstriaExcludedTxs") + excludedTransactions := s.eth.TxPool().AstriaExcludedFromBlock() + includedTransactions := make([]*sequencerblockv1alpha1.RollupData, 0, len(block.Transactions())) + log.Info("excluded txs", "count", len(*excludedTransactions)) + for _, blockTx := range block.Transactions() { + // ensure blockTx is not in excludedTxs + found := false + for _, tx := range *excludedTransactions { + if tx.Hash() == tx.Hash() { + found = true + log.Error("tx found in excluded txs", "blockTx hash", tx.Hash().Hex()) + break + } + } + if found { + // ignore tx which has been excluded + continue + } + + if blockTx.Type() == types.DepositTxType { + depositTx, ok := depositTxMapping[blockTx.Hash().Hex()] + if !ok { + log.Error("deposit blockTx not found in depositTxMapping", "blockTx hash", blockTx.Hash().Hex()) + return nil, status.Error(codes.Internal, "deposit blockTx not found in depositTxMapping") + } + + includedTransactions = append(includedTransactions, &sequencerblockv1alpha1.RollupData{Value: &sequencerblockv1alpha1.RollupData_Deposit{Deposit: depositTx}}) + + } else { + marshalledTx, err := blockTx.MarshalBinary() + if err != nil { + log.Error("failed to marshal transaction", "err", err) + return nil, status.Error(codes.Internal, "failed to marshal transaction") + } + includedTransactions = append(includedTransactions, &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx}, + }) + } + } + log.Info("Built included tx list", "count", len(includedTransactions)) + + // we do not insert the block to the chain if we just want to simulate the transactions + if !req.GetSimulateOnly() { + log.Info("Inserting block to chain") + err = s.bc.InsertBlockWithoutSetHead(block) + if err != nil { + log.Error("failed to insert block to chain", "hash", block.Hash(), "prevHash", req.PrevBlockHash, "err", err) + return nil, status.Error(codes.Internal, "failed to insert block to chain") + } + } else { + log.Info("Skipping inserting block to chain as simulateOnly is set") } // remove txs from original mempool s.eth.TxPool().ClearAstriaOrdered() - res := &astriaPb.Block{ + finalBlock := &astriaPb.Block{ Number: uint32(block.NumberU64()), Hash: block.Hash().Bytes(), ParentBlockHash: block.ParentHash().Bytes(), @@ -300,11 +405,16 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req * }, } - if next, ok := s.bc.Config().AstriaFeeCollectors[res.Number+1]; ok { + if next, ok := s.bc.Config().AstriaFeeCollectors[finalBlock.Number+1]; ok { s.nextFeeRecipient = next } - log.Info("ExecuteBlock completed", "block_num", res.Number, "timestamp", res.Timestamp) + res := &astriaPb.ExecuteBlockResponse{ + Block: finalBlock, + IncludedTransactions: includedTransactions, + } + + log.Info("Trusted Builder ExecuteBlock completed", "block_num", res.GetBlock().Number, "timestamp", res.GetBlock().Timestamp) totalExecutedTxCount.Inc(int64(len(block.Transactions()))) executeBlockSuccessCount.Inc(1) return res, nil @@ -334,7 +444,7 @@ func (s *ExecutionServiceServerV1Alpha2) GetCommitmentState(ctx context.Context, BaseCelestiaHeight: celestiaBlock, } - log.Info("GetCommitmentState completed", "soft_height", res.Soft.Number, "firm_height", res.Firm.Number, "base_celestia_height", res.BaseCelestiaHeight) + log.Debug("GetCommitmentState completed", "soft_height", res.Soft.Number, "firm_height", res.Firm.Number, "base_celestia_height", res.BaseCelestiaHeight) getCommitmentStateSuccessCount.Inc(1) s.getCommitmentStateCalled = true return res, nil @@ -410,7 +520,7 @@ func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Conte s.bc.SetCelestiaFinalized(firmBlock.Header(), req.CommitmentState.BaseCelestiaHeight) } - log.Info("UpdateCommitmentState completed", "soft_height", softBlock.NumberU64(), "firm_height", firmBlock.NumberU64()) + log.Debug("UpdateCommitmentState completed", "soft_height", softBlock.NumberU64(), "firm_height", firmBlock.NumberU64()) softCommitmentHeight.Update(int64(softBlock.NumberU64())) firmCommitmentHeight.Update(int64(firmBlock.NumberU64())) updateCommitmentStateSuccessCount.Inc(1) diff --git a/grpc/execution/server_test.go b/grpc/execution/server_test.go index 0e5caa66e..1212e23dc 100644 --- a/grpc/execution/server_test.go +++ b/grpc/execution/server_test.go @@ -1,6 +1,7 @@ package execution import ( + composerv1alpha1 "buf.build/gen/go/astria/composer-apis/protocolbuffers/go/astria/composer/v1alpha1" astriaPb "buf.build/gen/go/astria/execution-apis/protocolbuffers/go/astria/execution/v1alpha2" primitivev1 "buf.build/gen/go/astria/primitives/protocolbuffers/go/astria/primitive/v1" sequencerblockv1alpha1 "buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go/astria/sequencerblock/v1alpha1" @@ -11,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/golang/protobuf/proto" "github.com/holiman/uint256" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" @@ -202,46 +204,89 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlock(t *testing.T) { tests := []struct { description string callGenesisInfoAndGetCommitmentState bool - numberOfTxs int + noOfTxs int + noOfBuilderBundleTxs int prevBlockHash []byte timestamp uint64 - depositTxAmount *big.Int // if this is non zero then we send a deposit tx + noOfDepositTxs int + simulateOnly bool expectedReturnCode codes.Code }{ { description: "ExecuteBlock without calling GetGenesisInfo and GetCommitmentState", callGenesisInfoAndGetCommitmentState: false, - numberOfTxs: 5, + noOfTxs: 5, + noOfBuilderBundleTxs: 0, prevBlockHash: ethservice.BlockChain().GetBlockByNumber(2).Hash().Bytes(), timestamp: ethservice.BlockChain().GetBlockByNumber(2).Time() + 2, - depositTxAmount: big.NewInt(0), + noOfDepositTxs: 0, + simulateOnly: false, expectedReturnCode: codes.PermissionDenied, }, { description: "ExecuteBlock with 5 txs and no deposit tx", callGenesisInfoAndGetCommitmentState: true, - numberOfTxs: 5, + noOfTxs: 5, + noOfBuilderBundleTxs: 0, prevBlockHash: ethservice.BlockChain().CurrentSafeBlock().Hash().Bytes(), timestamp: ethservice.BlockChain().CurrentSafeBlock().Time + 2, - depositTxAmount: big.NewInt(0), - expectedReturnCode: 0, + noOfDepositTxs: 0, + simulateOnly: false, + expectedReturnCode: codes.OK, }, { description: "ExecuteBlock with 5 txs and a deposit tx", callGenesisInfoAndGetCommitmentState: true, - numberOfTxs: 5, + noOfTxs: 5, + noOfBuilderBundleTxs: 0, prevBlockHash: ethservice.BlockChain().CurrentSafeBlock().Hash().Bytes(), timestamp: ethservice.BlockChain().CurrentSafeBlock().Time + 2, - depositTxAmount: big.NewInt(1000000000000000000), - expectedReturnCode: 0, + noOfDepositTxs: 1, + simulateOnly: false, + expectedReturnCode: codes.OK, + }, + { + description: "ExecuteBlock with 5 txs and no deposit tx in simulate only mode", + callGenesisInfoAndGetCommitmentState: true, + noOfTxs: 5, + noOfBuilderBundleTxs: 0, + prevBlockHash: ethservice.BlockChain().CurrentSafeBlock().Hash().Bytes(), + timestamp: ethservice.BlockChain().CurrentSafeBlock().Time + 2, + noOfDepositTxs: 0, + simulateOnly: true, + expectedReturnCode: codes.OK, + }, + { + description: "ExecuteBlock with 5 txs, no deposit tx and with 5 builder bundle txs in simulate only mode", + callGenesisInfoAndGetCommitmentState: true, + noOfTxs: 5, + noOfBuilderBundleTxs: 5, + prevBlockHash: ethservice.BlockChain().CurrentSafeBlock().Hash().Bytes(), + timestamp: ethservice.BlockChain().CurrentSafeBlock().Time + 2, + noOfDepositTxs: 0, + simulateOnly: true, + expectedReturnCode: codes.InvalidArgument, + }, + { + description: "ExecuteBlock with 5 txs, no deposit tx and with 5 builder bundle txs", + callGenesisInfoAndGetCommitmentState: true, + noOfTxs: 5, + noOfBuilderBundleTxs: 5, + prevBlockHash: ethservice.BlockChain().CurrentSafeBlock().Hash().Bytes(), + timestamp: ethservice.BlockChain().CurrentSafeBlock().Time + 2, + noOfDepositTxs: 0, + simulateOnly: false, + expectedReturnCode: codes.OK, }, { description: "ExecuteBlock with incorrect previous block hash", callGenesisInfoAndGetCommitmentState: true, - numberOfTxs: 5, + noOfTxs: 5, + noOfBuilderBundleTxs: 0, prevBlockHash: ethservice.BlockChain().GetBlockByNumber(2).Hash().Bytes(), timestamp: ethservice.BlockChain().GetBlockByNumber(2).Time() + 2, - depositTxAmount: big.NewInt(0), + noOfDepositTxs: 0, + simulateOnly: false, expectedReturnCode: codes.FailedPrecondition, }, } @@ -266,45 +311,89 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlock(t *testing.T) { } // create the txs to send - // create 5 txs txs := []*types.Transaction{} marshalledTxs := []*sequencerblockv1alpha1.RollupData{} - for i := 0; i < 5; i++ { - unsignedTx := types.NewTransaction(uint64(i), testToAddress, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil) + txsToCheck := []*sequencerblockv1alpha1.RollupData{} + + nonce := 0 + + if tt.noOfBuilderBundleTxs > 0 { + parentBlock := ethservice.BlockChain().CurrentSafeBlock() + + // create the BuilderBundlePacket + builderBundle := &composerv1alpha1.BuilderBundlePacket{ + Bundle: &composerv1alpha1.BuilderBundle{ + Transactions: []*sequencerblockv1alpha1.RollupData{}, + ParentHash: parentBlock.Hash().Bytes(), + }, + } + + // create noOfTxsInBuilderBundle txs + for i := 0; i < tt.noOfBuilderBundleTxs; i++ { + unsignedTx := types.NewTransaction(uint64(nonce), testToAddress, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil) + tx, err := types.SignTx(unsignedTx, types.LatestSigner(ethservice.BlockChain().Config()), testKey) + require.Nil(t, err, "Failed to sign tx") + + marshalledTx, err := tx.MarshalBinary() + require.Nil(t, err, "Failed to marshal tx") + rollupData := &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx}, + } + txsToCheck = append(txsToCheck, rollupData) + builderBundle.Bundle.Transactions = append(builderBundle.Bundle.Transactions, rollupData) + nonce += 1 + } + + // add the builderBundle to the list of transactions + marshalledProto, err := proto.Marshal(builderBundle) + require.Nil(t, err, "Failed to marshal builder bundle") + marshalledTxs = append(marshalledTxs, &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledProto}, + }) + } + + for i := 0; i < tt.noOfTxs; i++ { + unsignedTx := types.NewTransaction(uint64(nonce), testToAddress, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil) tx, err := types.SignTx(unsignedTx, types.LatestSigner(ethservice.BlockChain().Config()), testKey) require.Nil(t, err, "Failed to sign tx") txs = append(txs, tx) marshalledTx, err := tx.MarshalBinary() require.Nil(t, err, "Failed to marshal tx") - marshalledTxs = append(marshalledTxs, &sequencerblockv1alpha1.RollupData{ + rollupData := &sequencerblockv1alpha1.RollupData{ Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx}, - }) - } - - // create deposit tx if depositTxAmount is non zero - if tt.depositTxAmount.Cmp(big.NewInt(0)) != 0 { - depositAmount := bigIntToProtoU128(tt.depositTxAmount) - bridgeAddress := ethservice.BlockChain().Config().AstriaBridgeAddressConfigs[0].BridgeAddress - bridgeAssetDenom := ethservice.BlockChain().Config().AstriaBridgeAddressConfigs[0].AssetDenom - - // create new chain destination address for better testing - chainDestinationAddressPrivKey, err := crypto.GenerateKey() - require.Nil(t, err, "Failed to generate chain destination address") - - chainDestinationAddress := crypto.PubkeyToAddress(chainDestinationAddressPrivKey.PublicKey) + } + txsToCheck = append(txsToCheck, rollupData) + marshalledTxs = append(marshalledTxs, rollupData) - depositTx := &sequencerblockv1alpha1.RollupData{Value: &sequencerblockv1alpha1.RollupData_Deposit{Deposit: &sequencerblockv1alpha1.Deposit{ - BridgeAddress: &primitivev1.Address{ - Bech32M: bridgeAddress, - }, - Asset: bridgeAssetDenom, - Amount: depositAmount, - RollupId: genesisInfo.RollupId, - DestinationChainAddress: chainDestinationAddress.String(), - }}} + nonce += 1 + } - marshalledTxs = append(marshalledTxs, depositTx) + // create deposit tx if noOfDepositTxs is non zero + if tt.noOfDepositTxs > 0 { + for i := 0; i < tt.noOfDepositTxs; i++ { + depositAmount := bigIntToProtoU128(big.NewInt(1000000000000000000)) + bridgeAddress := ethservice.BlockChain().Config().AstriaBridgeAddressConfigs[0].BridgeAddress + bridgeAssetDenom := ethservice.BlockChain().Config().AstriaBridgeAddressConfigs[0].AssetDenom + + // create new chain destination address for better testing + chainDestinationAddressPrivKey, err := crypto.GenerateKey() + require.Nil(t, err, "Failed to generate chain destination address") + + chainDestinationAddress := crypto.PubkeyToAddress(chainDestinationAddressPrivKey.PublicKey) + + depositTx := &sequencerblockv1alpha1.RollupData{Value: &sequencerblockv1alpha1.RollupData_Deposit{Deposit: &sequencerblockv1alpha1.Deposit{ + BridgeAddress: &primitivev1.Address{ + Bech32M: bridgeAddress, + }, + Asset: bridgeAssetDenom, + Amount: depositAmount, + RollupId: &primitivev1.RollupId{Inner: genesisInfo.RollupId.Inner}, + DestinationChainAddress: chainDestinationAddress.String(), + }}} + txsToCheck = append(txsToCheck, depositTx) + marshalledTxs = append(marshalledTxs, depositTx) + } } executeBlockReq := &astriaPb.ExecuteBlockRequest{ @@ -313,6 +402,7 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlock(t *testing.T) { Seconds: int64(tt.timestamp), }, Transactions: marshalledTxs, + SimulateOnly: tt.simulateOnly, } executeBlockRes, err := serviceV1Alpha1.ExecuteBlock(context.Background(), executeBlockReq) @@ -321,6 +411,16 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlock(t *testing.T) { require.Equal(t, tt.expectedReturnCode, status.Code(err), "ExecuteBlock failed") } if err == nil { + block := ethservice.BlockChain().GetBlockByHash(common.BytesToHash(executeBlockRes.Block.Hash)) + if tt.simulateOnly { + require.Nil(t, block, "Block should not be found in blockchain") + } else { + require.NotNil(t, block, "Block not found in blockchain") + require.Equal(t, block.Hash(), common.BytesToHash(executeBlockRes.Block.Hash), "Block hash is not correct") + require.Equal(t, block.ParentHash(), common.BytesToHash(executeBlockRes.Block.ParentBlockHash), "Parent Block Hash is not correct") + require.Equal(t, block.NumberU64(), uint64(executeBlockRes.Block.Number), "Block number is not correct") + } + require.NotNil(t, executeBlockRes, "ExecuteBlock response is nil") astriaOrdered := ethservice.TxPool().AstriaOrdered() @@ -331,6 +431,31 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlock(t *testing.T) { require.Nil(t, err, "GetCommitmentState failed") require.Exactly(t, commitmentStateBeforeExecuteBlock, commitmentStateAfterExecuteBlock, "Commitment state should not be updated") + + includedTransactions := executeBlockRes.GetIncludedTransactions() + require.NotNil(t, includedTransactions, "IncludedTransactions is nil") + require.Equal(t, tt.noOfBuilderBundleTxs+tt.noOfTxs+tt.noOfDepositTxs, len(includedTransactions), "IncludedTransactions length is not correct") + + // check if includedTransactions is the same as marshalled transactions without considering order + for _, includedTx := range includedTransactions { + found := false + for _, tx := range txsToCheck { + if includedDeposit := includedTx.GetDeposit(); includedDeposit != nil { + // check if included deposit tx is the same as the one we sent + depositTx := tx.GetDeposit() + if depositTx != nil && depositTx.GetAmount().Lo == includedDeposit.GetAmount().Lo && depositTx.GetAmount().Hi == includedDeposit.GetAmount().Hi { + found = true + break + } + } else { + if bytes.Equal(includedTx.GetSequencedData(), tx.GetSequencedData()) { + found = true + break + } + } + } + require.True(t, found, "Included transaction not found in marshalled transactions") + } } }) @@ -393,7 +518,7 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlockAndUpdateCommitment(t *testi }, Asset: bridgeAssetDenom, Amount: depositAmount, - RollupId: genesisInfo.RollupId, + RollupId: &primitivev1.RollupId{Inner: genesisInfo.RollupId.Inner}, DestinationChainAddress: chainDestinationAddress.String(), }}} @@ -420,16 +545,16 @@ func TestExecutionServiceServerV1Alpha2_ExecuteBlockAndUpdateCommitment(t *testi updateCommitmentStateReq := &astriaPb.UpdateCommitmentStateRequest{ CommitmentState: &astriaPb.CommitmentState{ Soft: &astriaPb.Block{ - Hash: executeBlockRes.Hash, - ParentBlockHash: executeBlockRes.ParentBlockHash, - Number: executeBlockRes.Number, - Timestamp: executeBlockRes.Timestamp, + Hash: executeBlockRes.GetBlock().Hash, + ParentBlockHash: executeBlockRes.GetBlock().ParentBlockHash, + Number: executeBlockRes.GetBlock().Number, + Timestamp: executeBlockRes.GetBlock().Timestamp, }, Firm: &astriaPb.Block{ - Hash: executeBlockRes.Hash, - ParentBlockHash: executeBlockRes.ParentBlockHash, - Number: executeBlockRes.Number, - Timestamp: executeBlockRes.Timestamp, + Hash: executeBlockRes.GetBlock().Hash, + ParentBlockHash: executeBlockRes.GetBlock().ParentBlockHash, + Number: executeBlockRes.GetBlock().Number, + Timestamp: executeBlockRes.GetBlock().Timestamp, }, BaseCelestiaHeight: commitmentState.BaseCelestiaHeight + 1, }, diff --git a/grpc/execution/validation.go b/grpc/execution/validation.go index dd31c2872..94a3fbf30 100644 --- a/grpc/execution/validation.go +++ b/grpc/execution/validation.go @@ -1,6 +1,7 @@ package execution import ( + composerv1alpha1 "buf.build/gen/go/astria/composer-apis/protocolbuffers/go/astria/composer/v1alpha1" sequencerblockv1alpha1 "buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go/astria/sequencerblock/v1alpha1" "crypto/sha256" "fmt" @@ -9,14 +10,15 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/golang/protobuf/proto" "math/big" ) -// `validateAndUnmarshalSequencerTx` validates and unmarshals the given rollup sequencer transaction. +// `validateAndUnmarshalTx` validates and unmarshals the given rollup sequencer transaction. // If the sequencer transaction is a deposit tx, we ensure that the asset ID is allowed and the bridge address is known. // If the sequencer transaction is not a deposit tx, we unmarshal the sequenced data into an Ethereum transaction. We ensure that the // tx is not a blob tx or a deposit tx. -func validateAndUnmarshalSequencerTx( +func validateAndUnmarshalTx( height uint64, tx *sequencerblockv1alpha1.RollupData, bridgeAddresses map[string]*params.AstriaBridgeAddressConfig, @@ -24,80 +26,146 @@ func validateAndUnmarshalSequencerTx( bridgeSenderAddress common.Address, ) (*types.Transaction, error) { if deposit := tx.GetDeposit(); deposit != nil { - bridgeAddress := deposit.BridgeAddress.GetBech32M() - bac, ok := bridgeAddresses[bridgeAddress] - if !ok { - return nil, fmt.Errorf("unknown bridge address: %s", bridgeAddress) - } + return validateAndUnmarshallDepositTx(height, tx, bridgeAddresses, bridgeAllowedAssets, bridgeSenderAddress) + } else { + return validateAndUnmarshallSequenceTx(tx) + } +} + +func validateAndUnmarshallDepositTx( + height uint64, + tx *sequencerblockv1alpha1.RollupData, + bridgeAddresses map[string]*params.AstriaBridgeAddressConfig, + bridgeAllowedAssets map[string]struct{}, + bridgeSenderAddress common.Address, +) (*types.Transaction, error) { + deposit := tx.GetDeposit() + bridgeAddress := deposit.BridgeAddress.GetBech32M() + bac, ok := bridgeAddresses[bridgeAddress] + if !ok { + return nil, fmt.Errorf("unknown bridge address: %s", bridgeAddress) + } + + if height < uint64(bac.StartHeight) { + return nil, fmt.Errorf("bridging asset %s from bridge %s not allowed before height %d", bac.AssetDenom, bridgeAddress, bac.StartHeight) + } + + if _, ok := bridgeAllowedAssets[deposit.Asset]; !ok { + return nil, fmt.Errorf("disallowed asset %s in deposit tx", deposit.Asset) + } - if height < uint64(bac.StartHeight) { - return nil, fmt.Errorf("bridging asset %s from bridge %s not allowed before height %d", bac.AssetDenom, bridgeAddress, bac.StartHeight) + if deposit.Asset != bac.AssetDenom { + return nil, fmt.Errorf("asset %s does not match bridge address %s asset", deposit.Asset, bridgeAddress) + } + + recipient := common.HexToAddress(deposit.DestinationChainAddress) + amount := bac.ScaledDepositAmount(protoU128ToBigInt(deposit.Amount)) + + if bac.Erc20Asset != nil { + log.Debug("creating deposit tx to mint ERC20 asset", "token", bac.AssetDenom, "erc20Address", bac.Erc20Asset.ContractAddress) + abi, err := contracts.AstriaBridgeableERC20MetaData.GetAbi() + if err != nil { + // this should never happen, as the abi is hardcoded in the contract bindings + return nil, fmt.Errorf("failed to get abi for erc20 contract for asset %s: %w", bac.AssetDenom, err) } - if _, ok := bridgeAllowedAssets[deposit.Asset]; !ok { - return nil, fmt.Errorf("disallowed asset %s in deposit tx", deposit.Asset) + // pack arguments for calling the `mint` function on the ERC20 contract + args := []interface{}{recipient, amount} + calldata, err := abi.Pack("mint", args...) + if err != nil { + return nil, err } - if deposit.Asset != bac.AssetDenom { - return nil, fmt.Errorf("asset %s does not match bridge address %s asset", deposit.Asset, bridgeAddress) + txdata := types.DepositTx{ + From: bridgeSenderAddress, + Value: new(big.Int), // don't need to set this, as we aren't minting the native asset + // mints cost ~14k gas, however this can vary based on existing storage, so we add a little extra as buffer. + // + // the fees are spent from the "bridge account" which is not actually a real account, but is instead some + // address defined by consensus, so the gas cost is not actually deducted from any account. + Gas: 16000, + To: &bac.Erc20Asset.ContractAddress, + Data: calldata, } - recipient := common.HexToAddress(deposit.DestinationChainAddress) - amount := bac.ScaledDepositAmount(protoU128ToBigInt(deposit.Amount)) + tx := types.NewTx(&txdata) + return tx, nil + } - if bac.Erc20Asset != nil { - log.Debug("creating deposit tx to mint ERC20 asset", "token", bac.AssetDenom, "erc20Address", bac.Erc20Asset.ContractAddress) - abi, err := contracts.AstriaBridgeableERC20MetaData.GetAbi() - if err != nil { - // this should never happen, as the abi is hardcoded in the contract bindings - return nil, fmt.Errorf("failed to get abi for erc20 contract for asset %s: %w", bac.AssetDenom, err) - } + txdata := types.DepositTx{ + From: bridgeSenderAddress, + To: &recipient, + Value: amount, + Gas: 0, + } + return types.NewTx(&txdata), nil +} - // pack arguments for calling the `mint` function on the ERC20 contract - args := []interface{}{recipient, amount} - calldata, err := abi.Pack("mint", args...) - if err != nil { - return nil, err - } +func validateAndUnmarshallSequenceTx( + tx *sequencerblockv1alpha1.RollupData, +) (*types.Transaction, error) { + ethTx := new(types.Transaction) + err := ethTx.UnmarshalBinary(tx.GetSequencedData()) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal sequenced data into transaction: %w. tx hash: %s", err, sha256.Sum256(tx.GetSequencedData())) + } + + if ethTx.Type() == types.DepositTxType { + return nil, fmt.Errorf("deposit tx not allowed in sequenced data. tx hash: %s", sha256.Sum256(tx.GetSequencedData())) + } + + if ethTx.Type() == types.BlobTxType { + return nil, fmt.Errorf("blob tx not allowed in sequenced data. tx hash: %s", sha256.Sum256(tx.GetSequencedData())) + } + + return ethTx, nil +} - txdata := types.DepositTx{ - From: bridgeSenderAddress, - Value: new(big.Int), // don't need to set this, as we aren't minting the native asset - // mints cost ~14k gas, however this can vary based on existing storage, so we add a little extra as buffer. - // - // the fees are spent from the "bridge account" which is not actually a real account, but is instead some - // address defined by consensus, so the gas cost is not actually deducted from any account. - Gas: 16000, - To: &bac.Erc20Asset.ContractAddress, - Data: calldata, +func extractBuilderBundleAndTxs(txs []*sequencerblockv1alpha1.RollupData, height uint64, + bridgeAddresses map[string]*params.AstriaBridgeAddressConfig, + bridgeAllowedAssets map[string]struct{}, + bridgeSenderAddress common.Address) (*composerv1alpha1.BuilderBundlePacket, types.Transactions, map[string]*sequencerblockv1alpha1.Deposit, error) { + // Extract the builder bundle from the sequencer txs + var builderBundle *composerv1alpha1.BuilderBundlePacket + ethTxs := types.Transactions{} + // this is a mapping from tx hash to depositTx, we use this when we need to simulate the txs to map the tx hash to the depositTx + depositTxMapping := map[string]*sequencerblockv1alpha1.Deposit{} + for _, tx := range txs { + if deposit := tx.GetDeposit(); deposit != nil { + tx, err := validateAndUnmarshallDepositTx(height, tx, bridgeAddresses, bridgeAllowedAssets, bridgeSenderAddress) + if err != nil { + return nil, nil, nil, err } + depositTxMapping[tx.Hash().Hex()] = deposit + ethTxs = append(ethTxs, tx) + } else { + // check if we can unmarshall the sequence data to a BuilderBundlePacket + tempBuilderBundle := &composerv1alpha1.BuilderBundlePacket{} + err := proto.Unmarshal(tx.GetSequencedData(), tempBuilderBundle) + if err == nil { + // we found a builder bundle, we first check if we got a duplicate builder bundle. if we did + // we throw an error + // TODO - we could just ignore the duplicate builder bundle?? + if builderBundle != nil { + return nil, nil, nil, fmt.Errorf("duplicate builder bundle found in sequencer txs") + } - tx := types.NewTx(&txdata) - return tx, nil - } + // duplicate builder bundle not found, we set the builder bundle to the temp builder bundle + builderBundle = tempBuilderBundle - txdata := types.DepositTx{ - From: bridgeSenderAddress, - To: &recipient, - Value: amount, - Gas: 0, - } - return types.NewTx(&txdata), nil - } else { - ethTx := new(types.Transaction) - err := ethTx.UnmarshalBinary(tx.GetSequencedData()) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal sequenced data into transaction: %w. tx hash: %s", err, sha256.Sum256(tx.GetSequencedData())) - } + } else { + // if its not a builder bundle, then it should be a regular eth tx + ethTx, err := validateAndUnmarshallSequenceTx(tx) + if err != nil { + return nil, nil, nil, err + } - if ethTx.Type() == types.DepositTxType { - return nil, fmt.Errorf("deposit tx not allowed in sequenced data. tx hash: %s", sha256.Sum256(tx.GetSequencedData())) - } + ethTxs = append(ethTxs, ethTx) + } - if ethTx.Type() == types.BlobTxType { - return nil, fmt.Errorf("blob tx not allowed in sequenced data. tx hash: %s", sha256.Sum256(tx.GetSequencedData())) } - return ethTx, nil } + + return builderBundle, ethTxs, depositTxMapping, nil } diff --git a/grpc/execution/validation_test.go b/grpc/execution/validation_test.go index b715041b4..44cd99cd3 100644 --- a/grpc/execution/validation_test.go +++ b/grpc/execution/validation_test.go @@ -1,6 +1,8 @@ package execution import ( + composerv1alpha1 "buf.build/gen/go/astria/composer-apis/protocolbuffers/go/astria/composer/v1alpha1" + "github.com/golang/protobuf/proto" "math/big" "testing" @@ -52,6 +54,103 @@ func generateBech32MAddress() string { return bech32m } +func TestExtractBuilderBundleAndTxs(t *testing.T) { + ethservice, serviceV1Alpha1 := setupExecutionService(t, 10) + + invalidHeightBridgeAssetDenom := "invalid-height-asset-denom" + invalidHeightBridgeAddressBech32m := generateBech32MAddress() + serviceV1Alpha1.bridgeAddresses[invalidHeightBridgeAddressBech32m] = ¶ms.AstriaBridgeAddressConfig{ + AssetDenom: invalidHeightBridgeAssetDenom, + StartHeight: 100, + } + + tests := []struct { + description string + noOfTxsInBuilderBundle int + noOfOtherTxs int + }{ + { + description: "empty list of transactions", + noOfTxsInBuilderBundle: 0, + noOfOtherTxs: 0, + }, + { + description: "list of transactions without builderBundlePacket", + noOfTxsInBuilderBundle: 0, + noOfOtherTxs: 5, + }, + { + description: "list of transactions with builderBundlePacket", + noOfTxsInBuilderBundle: 5, + noOfOtherTxs: 5, + }, + { + description: "one transaction with builderBundlePacket", + noOfTxsInBuilderBundle: 5, + noOfOtherTxs: 0, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + marshalledTxs := []*sequencerblockv1alpha1.RollupData{} + + // create the other txs + nonce := 0 + for i := 0; i < test.noOfOtherTxs; i++ { + unsignedTx := types.NewTransaction(uint64(nonce), testToAddress, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil) + tx, err := types.SignTx(unsignedTx, types.LatestSigner(ethservice.BlockChain().Config()), testKey) + require.Nil(t, err, "Failed to sign tx") + + marshalledTx, err := tx.MarshalBinary() + require.Nil(t, err, "Failed to marshal tx") + marshalledTxs = append(marshalledTxs, &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx}, + }) + + nonce += 1 + } + + if test.noOfTxsInBuilderBundle > 0 { + // create the BuilderBundlePacket + builderBundle := &composerv1alpha1.BuilderBundlePacket{ + Bundle: &composerv1alpha1.BuilderBundle{ + Transactions: []*sequencerblockv1alpha1.RollupData{}, + ParentHash: nil, + }, + } + + // create noOfTxsInBuilderBundle txs + for i := 0; i < test.noOfTxsInBuilderBundle; i++ { + unsignedTx := types.NewTransaction(uint64(nonce), testToAddress, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil) + tx, err := types.SignTx(unsignedTx, types.LatestSigner(ethservice.BlockChain().Config()), testKey) + require.Nil(t, err, "Failed to sign tx") + + marshalledTx, err := tx.MarshalBinary() + require.Nil(t, err, "Failed to marshal tx") + builderBundle.Bundle.Transactions = append(builderBundle.Bundle.Transactions, &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx}, + }) + nonce += 1 + } + + // add the builderBundle to the list of transactions + marshalledProto, err := proto.Marshal(builderBundle) + require.Nil(t, err, "Failed to marshal builder bundle") + marshalledTxs = append(marshalledTxs, &sequencerblockv1alpha1.RollupData{ + Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledProto}, + }) + } + + builderBundlePacket, otherTxs, _, err := extractBuilderBundleAndTxs(marshalledTxs, 2, serviceV1Alpha1.bridgeAddresses, serviceV1Alpha1.bridgeAllowedAssets, common.Address{}) + require.Nil(t, err, "Failed to extract builder bundle and txs") + require.Equal(t, test.noOfTxsInBuilderBundle, len(builderBundlePacket.GetBundle().GetTransactions()), "Incorrect number of txs in builder bundle") + require.Equal(t, test.noOfOtherTxs, len(otherTxs), "Incorrect number of other txs") + }) + } + +} + func TestSequenceTxValidation(t *testing.T) { ethservice, serviceV1Alpha1 := setupExecutionService(t, 10) @@ -180,7 +279,7 @@ func TestSequenceTxValidation(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { - _, err := validateAndUnmarshalSequencerTx(2, test.sequencerTx, serviceV1Alpha1.bridgeAddresses, serviceV1Alpha1.bridgeAllowedAssets, common.Address{}) + _, err := validateAndUnmarshalTx(2, test.sequencerTx, serviceV1Alpha1.bridgeAddresses, serviceV1Alpha1.bridgeAllowedAssets, common.Address{}) if test.wantErr == "" && err == nil { return } diff --git a/miner/worker.go b/miner/worker.go index 7b36a2e87..740b9eca7 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -194,6 +194,9 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e if err != nil { return err } + if receipt.Status == types.ReceiptStatusFailed { + return core.ErrTxReverted + } env.txs = append(env.txs, tx) env.receipts = append(env.receipts, receipt) env.tcount++ @@ -286,12 +289,16 @@ func (miner *Miner) commitAstriaTransactions(env *environment, txs *types.Transa case errors.Is(err, core.ErrNonceTooLow): // New head notification data race between the transaction pool and miner, shift log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce()) + case errors.Is(err, core.ErrTxReverted): + // Transaction failed, discard the transaction and get the next in line + log.Trace("Transaction reverted", "hash", tx.Hash(), "err", err) default: // Strange error, discard the transaction and get the next in line (note, the // nonce-too-high clause will prevent us from executing in vain). log.Debug("Transaction failed, account skipped", "hash", tx.Hash(), "err", err) } if err != nil { + log.Error("Removing invalid transaction", "hash", tx.Hash(), "from", from, "err", err) log.Trace("Marking transaction as invalid", "hash", tx.Hash(), "err", err) miner.txpool.AddToAstriaExcludedFromBlock(tx) }