Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

chore(state-transition): flipped transaction context attributes logic #2451

Merged
merged 20 commits into from
Feb 4, 2025

Conversation

abi87
Copy link
Collaborator

@abi87 abi87 commented Jan 31, 2025

most of the attributes in transaction.Context have negated logic which does not feel natural to me.
This PR flips that, so that we would have VerifyPayload instead of SkipPayloadVerification etc

@abi87 abi87 self-assigned this Jan 31, 2025
Copy link

codecov bot commented Jan 31, 2025

Codecov Report

Attention: Patch coverage is 20.51282% with 124 lines in your changes missing coverage. Please review.

Project coverage is 32.28%. Comparing base (7abf2d8) to head (245c368).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
primitives/transition/context.go 0.00% 50 Missing ⚠️
beacon/blockchain/finalize_block.go 0.00% 35 Missing ⚠️
beacon/validator/block_builder.go 0.00% 16 Missing ⚠️
beacon/blockchain/process_proposal.go 0.00% 14 Missing ⚠️
state-transition/core/state_processor_payload.go 50.00% 2 Missing and 2 partials ⚠️
node-core/components/state_processor.go 0.00% 2 Missing ⚠️
state-transition/core/state_processor.go 75.00% 1 Missing and 1 partial ⚠️
state-transition/core/state_processor_randao.go 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2451      +/-   ##
==========================================
- Coverage   32.35%   32.28%   -0.08%     
==========================================
  Files         350      350              
  Lines       15597    15634      +37     
  Branches       20       20              
==========================================
  Hits         5047     5047              
- Misses      10187    10224      +37     
  Partials      363      363              
Files with missing lines Coverage Δ
beacon/blockchain/service.go 0.00% <ø> (ø)
beacon/validator/service.go 0.00% <ø> (ø)
node-core/components/api.go 0.00% <ø> (ø)
node-core/components/chain_service.go 0.00% <ø> (ø)
node-core/components/validator_service.go 0.00% <ø> (ø)
state-transition/core/state_processor_genesis.go 41.07% <100.00%> (ø)
state-transition/core/state_processor_signature.go 0.00% <ø> (ø)
state-transition/core/state_processor_staking.go 62.79% <100.00%> (+0.88%) ⬆️
...tate-transition/core/state_processor_validators.go 70.96% <100.00%> (ø)
...ate-transition/core/state_processor_withdrawals.go 50.61% <ø> (ø)
... and 10 more

@abi87 abi87 marked this pull request as ready for review January 31, 2025 21:14
@abi87 abi87 requested a review from a team as a code owner January 31, 2025 21:14
Copy link
Contributor

@shotes shotes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits, otherwise LGTM

primitives/transition/context.go Outdated Show resolved Hide resolved
state-transition/core/types.go Outdated Show resolved Hide resolved
@abi87 abi87 requested review from rezbera and shotes January 31, 2025 22:04
@abi87 abi87 enabled auto-merge (squash) January 31, 2025 22:04
@abi87 abi87 disabled auto-merge January 31, 2025 22:05
@abi87 abi87 requested a review from rezbera January 31, 2025 22:16
@@ -37,7 +37,7 @@ import (

// StateProcessor is a basic Processor, which takes care of the
// main state transition for the beacon chain.
type StateProcessor[ContextT Context] struct {
type StateProcessor struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're fixing this I love the removal of generics. But I would prefer using the transition.Context as an interface so that the fields of the struct are not mutable in the stateProcessor. Thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a slight preference for the current proposal (exported attributes).
If we keep the getter, I think we should unexport the attributes and so introduce a constructor too.
Happy to go with the majority here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @berachain/core

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for un-exporting the struct fields initialized via NewXXX method and having simple read only getters.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added encapsulation, LMK how do you like this

Copy link
Contributor

@rezbera rezbera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is net improvement as is - lgtm

Comment on lines +87 to +109
func (c *Context) WithMeterGas(meter bool) *Context {
c.meterGas = meter
return c
}

func (c *Context) WithOptimisticEngine(optimistic bool) *Context {
c.optimisticEngine = optimistic
return c
}

func (c *Context) WithVerifyPayload(verifyPayload bool) *Context {
c.verifyPayload = verifyPayload
return c
}

func (c *Context) WithVerifyRandao(verifyRandao bool) *Context {
c.verifyRandao = verifyRandao
return c
}

func (c *Context) WithVerifyResult(verifyResult bool) *Context {
c.verifyResult = verifyResult
return c
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather pass attributes with these options to avoid a whole bunch of unreadable booleans in the constructor.
I would be down to do that if golang had proper typed enum. I think the solution I propose here is all in all the ones with the least code written (that does not pass booleans in the ctor)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we may use opts pattern instead as otherwise we could update Context after initialization. Not a big deal though if we use readonly interface for accessing fields

Comment on lines +80 to +82
verifyPayload: true,
verifyRandao: true,
verifyResult: true,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rather set all validators to true by default. I think the safest is to explicitly switch them off

@@ -33,32 +33,6 @@ import (
"github.com/karalabe/ssz"
)

// Context defines an interface for managing state transition context.
type Context interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this Context interface should still be used so that only the read-only methods are usable in this package. Currently the Setters can still be called from within state-transition

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a transition.ReadOnlyContext interface

).
WithVerifyPayload(false).
WithVerifyRandao(false).
WithVerifyResult(false).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically WithVerifyRandao should be true cause SkiValidateRandao was set to the default value of false.
However the intention of the tests was to skip these checks at all and focus on the state transition, so it's ok to not verify randao (and this PR makes it more explicit that it currently is)

@@ -26,73 +26,130 @@ import (
"github.com/berachain/beacon-kit/primitives/math"
)

// ReadOnlyContext defines an interface for managing state transition context.
type ReadOnlyContext interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually prefer the pattern of the package that uses a type defines the interface in their own package. Rather than exporting a global interface

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really necessary when we have only packages and not modules? I think a single interface reduced code duplication

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not absolutely necessary. I generally like following this pattern and is used throughout the repo https://medium.com/@mbinjamil/using-interfaces-in-go-the-right-way-99384bc69d39

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://go.dev/wiki/CodeReviewComments:

Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values... Do not define interfaces before they are used: without a realistic example of usage, it is too difficult to see whether an interface is even necessary, let alone what methods it ought to contain.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I dropped the interface from transition.Context file and ended up having a single one in state-processor.
Basically the only use of this interface is using this as parameter in Transition method, so I think this is fine

@@ -26,73 +26,130 @@ import (
"github.com/berachain/beacon-kit/primitives/math"
)

// ReadOnlyContext defines an interface for managing state transition context.
type ReadOnlyContext interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this

Comment on lines +87 to +109
func (c *Context) WithMeterGas(meter bool) *Context {
c.meterGas = meter
return c
}

func (c *Context) WithOptimisticEngine(optimistic bool) *Context {
c.optimisticEngine = optimistic
return c
}

func (c *Context) WithVerifyPayload(verifyPayload bool) *Context {
c.verifyPayload = verifyPayload
return c
}

func (c *Context) WithVerifyRandao(verifyRandao bool) *Context {
c.verifyRandao = verifyRandao
return c
}

func (c *Context) WithVerifyResult(verifyResult bool) *Context {
c.verifyResult = verifyResult
return c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we may use opts pattern instead as otherwise we could update Context after initialization. Not a big deal though if we use readonly interface for accessing fields

Copy link
Contributor

@calbera calbera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@abi87 abi87 merged commit 8bd60c6 into main Feb 4, 2025
19 checks passed
@abi87 abi87 deleted the flip-transaction-context-logic branch February 4, 2025 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants