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

New external staking events #131

Merged
merged 11 commits into from
Oct 7, 2024

Conversation

KonradStaniec
Copy link
Collaborator

@KonradStaniec KonradStaniec commented Oct 4, 2024

Implements events generation as described in https://babylonlabs.atlassian.net/wiki/spaces/BABYLON/pages/31195227/API+asks+for+BBN+node

Few caveats:

  • for in delegation creation event we have mulitple finality providers keys to avoid breaking changes for phase-3
  • generation of event responsible for expiry happens in BeginBlocker so that unbonding early and unbonding through expiry have are retrieved in different way

This pr handles only staking events, finality provider events will be added in separate pr.

@KonradStaniec KonradStaniec requested a review from a team as a code owner October 4, 2024 14:11
@KonradStaniec KonradStaniec requested review from gitferry, Lazar955 and jrwbabylonlab and removed request for a team October 4, 2024 14:11
@@ -57,11 +57,28 @@ func (k Keeper) AddBTCDelegation(ctx sdk.Context, btcDel *types.BTCDelegation) e
panic(fmt.Errorf("failed to emit EventBTCDelegationStateUpdate for the new pending BTC delegation: %w", err))
}

if err := ctx.EventManager().EmitTypedEvent(types.NewBtcDelCreationEvent(
Copy link
Member

Choose a reason for hiding this comment

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

Can L51-58 be removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hmm we should emit both events, but it can be simplified by using EmitTypedEvents(tevs ...proto.Message) . Will do that.

Copy link
Member

Choose a reason for hiding this comment

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

Why is it the case? in my mind the former event only contains a subset of the latter event and they share the same type of consumers

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

there are at least two advantages:

  1. consumers that do not want to process the "fat" event can only follow the state state updates events
  2. consumers know the initial state of created delegation i.e that is is PENDING. Without it they would need to either assume some state or we would need to add state field to EventBTCDelegationCreated

Copy link
Member

Choose a reason for hiding this comment

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

Hmm I'm not sure if there is a use case for the "slim" event, as the main consumer of this API is backend and other components do not seem to be interested in a newly pending delegation. Also EventBTCDelegationCreated seems to imply this BTC delegation is pending, and if not subsequent events will be emitted. That's why I would still prefer to keep each state transition to have a unique type of event.

Another thing is that the EventBTCDelegationStateUpdate event now has two use cases, one for voting power update and the other for serving API consumers. This is not a perfect idea as EventBTCDelegationStateUpdate is in fact a "DB" object. Now it seems to be a good time to fix this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Another thing is that the EventBTCDelegationStateUpdate event now has two use cases, one for voting power update and the other for serving API consumers. This is not a perfect idea as EventBTCDelegationStateUpdate is in fact a "DB" object. Now it seems to be a good time to fix this

This is good point, we should not expose db objects for external consumers. Either way, I would not tangle this into this pr which is about new events for api but create separate one for this purpose

Being totally honest I do not have strong preference here and imo both approaches have its merits. @jrwbabylonlab what would api prefer:

  1. Some special events, like delegation_creation + state transition events (i.e one event showing what is current state of delegation)
  2. Or set of different events like: delegation_creation, proof_of_inclusion_provided, unbonded_early, expired and covenant_quorum_reached ?

Choose a reason for hiding this comment

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

Option 2 offers more flexibility for the backend to power the UI. In addition to this, would it be possible to emit the key state transition event alongside the Option 2 events? For example, an isActive: true/false flag could be emitted when receiving the proof_of_inclusion_provided event (as an example).

That said, it’s not a major issue or blocker if this isn’t feasible.

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 avoid the flags as much as possible.

We could attach new state to every specific event if this would help the api ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

lets go option 2 then and add state field to each event that will reflect current state of the delegation

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

commit e9f16f6, implements option 2.

Now:

  • we have separate external and internal events
  • for external events every event have different type
  • every external event except EventCovenantSignatureRecevied carries info about state. EventCovenantSignatureRecevied does not carry state as there is separate event for reaching quorum EventCovenantQuroumReached which changes state
  • there are two separate events for EventBTCDelgationUnbondedEarly and EventBTCDelegationExpired both are block events.

@@ -111,6 +136,15 @@ func (k Keeper) addCovenantSigsToBTCDelegation(
activeEvent := types.NewEventPowerDistUpdateWithBTCDel(event)
btcTip := k.btclcKeeper.GetTipInfo(ctx)
k.addPowerDistUpdateEvent(ctx, btcTip.Height, activeEvent)
} else if btcDel.HasCovenantQuorums(params.CovenantQuorum) && !btcDel.HasInclusionProof() {
Copy link
Member

Choose a reason for hiding this comment

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

If conditions in L125 and L139 could be consolidated somehow, e.g.,

if btcDel.HasCovenantQuorums(params.CovenantQuorum) {
    if btcDel.HasInclusionProof() {

    } else {
        
    }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hmm this is probably matter of preference but I try do avoid deeply nested if/else blocks.

Though I will experiment with this a bit to check the readability.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hmm it looks good. I can leave with one level of nesting in this case 😅


stakingTxHash := btcDel.MustGetStakingTxHash()

if err := ctx.EventManager().EmitTypedEvent(types.NewInclusionProofEvent(
Copy link
Member

Choose a reason for hiding this comment

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

can L290-296 be removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

will switch to EmitTypedEvents(tevs ...proto.Message) 👍

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Copy link
Member

@gitferry gitferry left a comment

Choose a reason for hiding this comment

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

Great work!

Comment on lines 83 to 84
// timelock is the timelock of the staking tx specified in the BTC script
uint32 timelock = 5;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// timelock is the timelock of the staking tx specified in the BTC script
uint32 timelock = 5;
// staking_time is the timelock of the staking tx specified in the BTC script
uint32 staking_time = 5;

Seems we have been using staking_time everywhere in the staking library other than timelock

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good point lets be consistent then across the code base.

uint64 staking_amount = 6;
// unbonding_time is the time is timelock on unbonding tx chosen by the staker
uint32 unbonding_time = 7;
// unbonding_tx is hex encoded bytes of the unbonding tx
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// unbonding_tx is hex encoded bytes of the unbonding tx
// unbonding_tx is hex encoded bytes of the unsigned unbonding tx

string covenant_btc_pk_hex = 2;
// covenant_unbonding_signature_hex is the hex str of the BIP340 Schnorr
// signature of the covenant committee on the unbonding tx
string covenant_unbonding_signature_hex = 3;
Copy link
Member

Choose a reason for hiding this comment

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

why do we need to contain signature in the event?

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 imagine api will process those events, retrieve signatures from them and then staker will be able to unbond without consulting Babylon anymore

Comment on lines +117 to +119
// end_height is the end height of the BTC delegation
// it is calculated by end_height = start_height + staking_time
uint64 end_height = 3;
Copy link
Member

Choose a reason for hiding this comment

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

can end_height be calculated on the subscriber's sider?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

probably, but tbh 4bytes is small price to pay and we already have all the information on hand when generating this event.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@KonradStaniec
Copy link
Collaborator Author

@SebastianElvis I have applied all the comment so I will merge it now. If there will be some missing things I will improve them in follow up.

@KonradStaniec KonradStaniec merged commit efeb745 into main Oct 7, 2024
18 checks passed
@KonradStaniec KonradStaniec deleted the konradstaniec/external-staking-events branch October 7, 2024 14:12
gitferry added a commit that referenced this pull request Oct 9, 2024
…nge (#144)

This is a follow-up PR of #131. This PR implements events generation
related to finality providers as described in
https://babylonlabs.atlassian.net/wiki/spaces/BABYLON/pages/31195227/API+asks+for+BBN+node.
In particular, this PR

1. adds events for fp creation and editing, which are emitted within
corresponding message handlers
2. adds events for fp status update, i.e., active, inactive, jailed,
slashed, which are emitted during voting power table update per
BeginBlock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants