Conversation
This reverts commit 63996b3.
|
#370 was opened while working on this |
| return err | ||
| case RoundChangeMsgType: | ||
| return i.uponRoundChange(i.StartValue, msg, i.State.RoundChangeContainer, i.config.GetValueCheckF()) | ||
| return i.uponRoundChange(msg, i.State.RoundChangeContainer, i.config.GetValueCheckF()) |
There was a problem hiding this comment.
I noticed we're passing i.StartValue, i.State.RoundChangeContainer, and i.config.GetValueCheckF() as arguments to the function. Given these are accessed via the instance i, could someone help clarify the rationale behind explicitly passing these as parameters instead of accessing them directly within the uponRoundChange method?
Is there a specific design choice or benefit we're aiming for by structuring the call this way? For instance, does this approach enhance testability, readability, or separation of concerns in a way that accessing them directly within the function would not?
There was a problem hiding this comment.
ditto
i.uponProposal
i.uponPrepare
i.UponCommit
There was a problem hiding this comment.
@GalRogozinski I agree with this, either only pass and not save (if its only used within these function) or save and don't pass.
There was a problem hiding this comment.
this is out of scope of PR, but can be done
| return err | ||
| case RoundChangeMsgType: | ||
| return i.uponRoundChange(i.StartValue, msg, i.State.RoundChangeContainer, i.config.GetValueCheckF()) | ||
| return i.uponRoundChange(msg, i.State.RoundChangeContainer, i.config.GetValueCheckF()) |
There was a problem hiding this comment.
case CommitMsgType:
decided, decidedValue, aggregatedCommit, err = i.UponCommit(msg, i.State.CommitContainer)
if decided {
i.State.Decided = decided
i.State.DecidedValue = decidedValue
}
return errnot related to the change, but we should check for err before assign
| } | ||
| if err = valueCheckF(value); err != nil { | ||
| fmt.Printf("%s\n", err.Error()) | ||
| return |
There was a problem hiding this comment.
should we also return if CreateProposal returns an error?
| return nil | ||
| } | ||
|
|
||
| // DataFetcher asynchronusly fetches data from the beacon node upon instantiation |
There was a problem hiding this comment.
| // DataFetcher asynchronusly fetches data from the beacon node upon instantiation | |
| // DataFetcher asynchronously fetches data from the beacon node upon instantiation |
| } | ||
|
|
||
| // DataFetcher asynchronusly fetches data from the beacon node upon instantiation | ||
| type DataFetcher struct { |
There was a problem hiding this comment.
Why not interface? Using concrete types is not flexible and inconvenient for testing and when spec repo is used by other repositories
There was a problem hiding this comment.
@nkryuchkov @GalRogozinski
Usually I support using concrete types. As they are more predictable than interfaces. but this time you are using this concrete type as an interface so it might make more sense for it to be an interface ( but then also moved to the runners ).
the rule is -
Return concrete types
Receive interfaces
|
|
||
| // Start is an interface implementation | ||
| func (i *Instance) Start(value []byte, height Height) { | ||
| func (i *Instance) Start(cdFetcher *types.DataFetcher, height Height, valueCheckF ProposedValueCheckF) { |
There was a problem hiding this comment.
Can't we use the i.GetConfig().GetValueCheck() instead of using an argument? It seems a duplication to me
There was a problem hiding this comment.
I agree, if value check only used here then maybe we don't need it as part of Config.
| fmt.Printf("%s\n", err.Error()) | ||
| return |
There was a problem hiding this comment.
The error should be returned and not printed, no?
There was a problem hiding this comment.
apparently we printed errors in main before...
not sure why...
Maybe we should add errors and test them?
I will open an issue
| if proposer(state, config, roundChangeMsg.QBFTMessage.Round) != state.CommitteeMember.OperatorID { | ||
| return nil, errors.New("not proposer") | ||
| } |
There was a problem hiding this comment.
The same check is done below. Any reason for duplicating it or we can remove it?
There was a problem hiding this comment.
where? I don't see it
| func chooseValueToPropose(roundChangeMsg *Message, cdFetcher *types.DataFetcher, preparedValue []byte) ([]byte, error) { | ||
| var valueToPropose []byte | ||
| if roundChangeMsg.RoundChangePrepared() { | ||
| valueToPropose = preparedValue | ||
| } else { | ||
| cd, err := cdFetcher.GetConsensusData() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| valueToPropose = cd | ||
| } | ||
| return valueToPropose, nil |
There was a problem hiding this comment.
Since the CDFetcher may update its value, we need to make sure that two different proposals for the same round can't be done. One way to do that is to check, in the validation of Round-Change messages, that the msg.Round is strictly above our current round.
There was a problem hiding this comment.
I don't understand.. we call this once per round
| if err := c.GetConfig().GetValueCheckF()(value); err != nil { | ||
| return errors.Wrap(err, "value invalid") | ||
| } | ||
| func (c *Controller) StartNewInstance(height Height, cdFetcher *types.DataFetcher) error { |
There was a problem hiding this comment.
Why not move the fetching logic outside of controller and pass an already fetched value? this of course also means determining that we are leaders outside of the controller. IMO it makes more sense than passing a fetcher. less changes to controller.
There was a problem hiding this comment.
thinking again this might not work if we need to fetch data after round change? but probably we should fetch data at the beginning of the slot regardless.
| // chooseValueToPropose | ||
| // If justifiedRoundChangeMsg has no prepare justification choose state value | ||
| // If justifiedRoundChangeMsg has prepare justification choose prepared value | ||
| func chooseValueToPropose(roundChangeMsg *Message, cdFetcher *types.DataFetcher, preparedValue []byte) ([]byte, error) { |
There was a problem hiding this comment.
since its only used in one place, this shouldn't be a method IMO, or at least the name should reflect that a long-awaited fetch is part of this function.
y0sher
left a comment
There was a problem hiding this comment.
you think its possible to do the fetching outside of the qbft controller?
|
@GalRogozinski (if/once you get back to this code) could you clarify/confirm whether this PR (after finished and merged) will support and be 100% compatible with the solution for the issue I described here (which we'll probably want to address at some point) ? I haven't looked through the code of this PR too much yet, but from cursory overview I think
lets consider the following scenario that shows when/why "value injection" might be needed:
|
|
Hey @iurii-ssv, Yeah, this PR is suppose to allow making async calls. So currently we need to wait for the next fork |
|
This pull request has been marked as stale due to 60 days of inactivity. |
Description
Closes #289
Instance will now fetch consensus data only if it is the round leader.
Timer starts before data is fetched to ensure it is synchronized across committee nodes.