Skip to content

Commit

Permalink
Merge pull request #4015 from oasisprotocol/kostko/stable/21.2.x/back…
Browse files Browse the repository at this point in the history
…port-startdebond-evt

[BACKPORT/21.2.x] go/staking: Add DebondingStartEscrowEvent
  • Loading branch information
kostko authored Jun 10, 2021
2 parents 26f0197 + 62dd7e4 commit 5511fc7
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .changelog/4014.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/staking: Add DebondingStartEscrowEvent

This makes it easier to reason about the debonded amounts, both in shares and
in base units.
3 changes: 3 additions & 0 deletions go/consensus/tendermint/apps/staking/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ var (
// (value is an api.AddEscrowEvent).
KeyAddEscrow = stakingState.KeyAddEscrow

// KeyDebondingStart is an ABCI event attribute key for DebondingStartEscrowEvents.
KeyDebondingStart = []byte("debonding_start")

// KeyAllowanceChange is an ABCI event attribute key for AllowanceChangeEvents.
KeyAllowanceChange = []byte("allowance_change")
)
20 changes: 19 additions & 1 deletion go/consensus/tendermint/apps/staking/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ func (app *stakingApplication) reclaimEscrow(ctx *api.Context, state *stakingSta
}
stakeAmount := baseUnits.Clone()

if _, err = from.Escrow.Debonding.Deposit(&deb.Shares, &baseUnits, stakeAmount); err != nil {
var debondingShares *quantity.Quantity
if debondingShares, err = from.Escrow.Debonding.Deposit(&deb.Shares, &baseUnits, stakeAmount); err != nil {
ctx.Logger().Error("ReclaimEscrow: failed to debond shares",
"err", err,
"to", toAddr,
Expand Down Expand Up @@ -404,6 +405,23 @@ func (app *stakingApplication) reclaimEscrow(ctx *api.Context, state *stakingSta
}
}

ctx.Logger().Debug("ReclaimEscrow: started debonding stake",
"from", reclaim.Account,
"to", toAddr,
"base_units", stakeAmount,
"active_shares", reclaim.Shares,
"debonding_shares", debondingShares,
)

evt := &staking.DebondingStartEscrowEvent{
Owner: toAddr,
Escrow: reclaim.Account,
Amount: *stakeAmount,
ActiveShares: reclaim.Shares,
DebondingShares: *debondingShares,
}
ctx.EmitEvent(api.NewEventBuilder(app.Name()).Attribute(KeyDebondingStart, cbor.Marshal(evt)))

return nil
}

Expand Down
10 changes: 10 additions & 0 deletions go/consensus/tendermint/staking/staking.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,16 @@ func EventsFromTendermint(

evt := &api.Event{Height: height, TxHash: txHash, Escrow: &api.EscrowEvent{Add: &e}}
events = append(events, evt)
case bytes.Equal(key, app.KeyDebondingStart):
// Debonding start escrow event.
var e api.DebondingStartEscrowEvent
if err := cbor.Unmarshal(val, &e); err != nil {
errs = multierror.Append(errs, fmt.Errorf("staking: corrupt DebondingStart escrow event: %w", err))
continue
}

evt := &api.Event{Height: height, TxHash: txHash, Escrow: &api.EscrowEvent{DebondingStart: &e}}
events = append(events, evt)
case bytes.Equal(key, app.KeyBurn):
// Burn event.
var e api.BurnEvent
Expand Down
22 changes: 19 additions & 3 deletions go/staking/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,10 @@ type BurnEvent struct {

// EscrowEvent is an escrow event.
type EscrowEvent struct {
Add *AddEscrowEvent `json:"add,omitempty"`
Take *TakeEscrowEvent `json:"take,omitempty"`
Reclaim *ReclaimEscrowEvent `json:"reclaim,omitempty"`
Add *AddEscrowEvent `json:"add,omitempty"`
Take *TakeEscrowEvent `json:"take,omitempty"`
DebondingStart *DebondingStartEscrowEvent `json:"debonding_start,omitempty"`
Reclaim *ReclaimEscrowEvent `json:"reclaim,omitempty"`
}

// Event signifies a staking event, returned via GetEvents.
Expand Down Expand Up @@ -259,6 +260,21 @@ type TakeEscrowEvent struct {
Amount quantity.Quantity `json:"amount"`
}

// DebondingStartEvent is the event emitted when the debonding process has
// started and the given number of active shares have been moved into the
// debonding pool and started debonding.
//
// Note that the given amount is valid at the time of debonding start and
// may not correspond to the final debonded amount in case any escrowed
// stake is subject to slashing.
type DebondingStartEscrowEvent struct {
Owner Address `json:"owner"`
Escrow Address `json:"escrow"`
Amount quantity.Quantity `json:"amount"`
ActiveShares quantity.Quantity `json:"active_shares"`
DebondingShares quantity.Quantity `json:"debonding_shares"`
}

// ReclaimEscrowEvent is the event emitted when stake is reclaimed from an
// escrow account back into owner's general account.
type ReclaimEscrowEvent struct {
Expand Down
32 changes: 32 additions & 0 deletions go/staking/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,38 @@ func testEscrowHelper( // nolint: gocyclo
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcAccData.Signer, tx)
require.NoError(err, "ReclaimEscrow")

// Wait for debonding start event.
select {
case rawEv := <-ch:
if rawEv.Escrow == nil || rawEv.Escrow.DebondingStart == nil {
t.Fatalf("expected debonding start event, got: %+v", rawEv)
}

ev := rawEv.Escrow.DebondingStart
require.NotNil(ev)
require.Equal(srcAccData.Address, ev.Owner, "Event: owner")
require.Equal(destAccData.Address, ev.Escrow, "Event: escrow")
require.Equal(totalEscrowed, &ev.Amount, "Event: amount")
require.Equal(reclaim.Shares, ev.ActiveShares, "Event: active shares")
require.Equal(totalEscrowed, &ev.DebondingShares, "Event: debonding shares") // Nothing else is debonding, so ratio is 1:1.

// Make sure that GetEvents also returns the debonding start event.
evts, grr := backend.GetEvents(context.Background(), rawEv.Height)
require.NoError(grr, "GetEvents")
var gotIt bool
for _, evt := range evts {
if evt.Escrow != nil && evt.Escrow.DebondingStart != nil {
if evt.Escrow.DebondingStart.Owner.Equal(ev.Owner) && evt.Escrow.DebondingStart.Escrow.Equal(ev.Escrow) && evt.Escrow.DebondingStart.Amount.Cmp(&ev.Amount) == 0 {
gotIt = true
break
}
}
}
require.EqualValues(true, gotIt, "GetEvents should return debonding start event")
case <-time.After(recvTimeout):
t.Fatalf("failed to receive debonding start event")
}

// Query debonding delegations.
debs, err = backend.DebondingDelegationsFor(context.Background(), &api.OwnerQuery{Owner: srcAccData.Address, Height: consensusAPI.HeightLatest})
require.NoError(err, "DebondingDelegations - after (in debonding)")
Expand Down

0 comments on commit 5511fc7

Please sign in to comment.