-
Notifications
You must be signed in to change notification settings - Fork 204
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nits, otherwise LGTM
@@ -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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @berachain/core
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this 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
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 |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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
verifyPayload: true, | ||
verifyRandao: true, | ||
verifyResult: true, |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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). |
There was a problem hiding this comment.
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)
primitives/transition/context.go
Outdated
@@ -26,73 +26,130 @@ import ( | |||
"github.com/berachain/beacon-kit/primitives/math" | |||
) | |||
|
|||
// ReadOnlyContext defines an interface for managing state transition context. | |||
type ReadOnlyContext interface { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
primitives/transition/context.go
Outdated
@@ -26,73 +26,130 @@ import ( | |||
"github.com/berachain/beacon-kit/primitives/math" | |||
) | |||
|
|||
// ReadOnlyContext defines an interface for managing state transition context. | |||
type ReadOnlyContext interface { |
There was a problem hiding this comment.
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
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 |
There was a problem hiding this comment.
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
…erachain/beacon-kit into flip-transaction-context-logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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 ofSkipPayloadVerification
etc