From 31a1f746f93052694234c553c7fd6be701abf78c Mon Sep 17 00:00:00 2001 From: hjort <> Date: Tue, 9 Feb 2021 14:16:09 +0100 Subject: [PATCH 01/49] Overview of keepers in object capability model (OCM) --- staking_system.puml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 staking_system.puml diff --git a/staking_system.puml b/staking_system.puml new file mode 100644 index 000000000000..cf9d77a7cf55 --- /dev/null +++ b/staking_system.puml @@ -0,0 +1,23 @@ +@startuml +'https://plantuml.com/class-diagram + +abstract class Staking +abstract class Distribution +abstract class Slashing +abstract class Evidence +abstract class Bank +abstract class Auth + +Bank <|-- Distribution +Auth <|-- Distribution +Staking <|-- Distribution + +Staking <|-- Evidence +Slashing <|-- Evidence + +Staking <|-- Slashing + +Auth <|-- Staking +Bank <|-- Staking + +@enduml \ No newline at end of file From 2c4ba34002f45820662cd35edc2b80e7c8264848 Mon Sep 17 00:00:00 2001 From: hjort <> Date: Tue, 9 Feb 2021 14:21:19 +0100 Subject: [PATCH 02/49] Updates to the spec, making clarifications --- x/staking/spec/03_messages.md | 10 +++++++++- x/staking/spec/08_params.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index 1155da93d97d..7a5c268111c0 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -63,11 +63,19 @@ This service message is expected to fail if: - the validator is does not exist - the validator is jailed - the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` +- the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares +- the amount delegated is less than the minimum allowed delegation If an existing `Delegation` object for provided addresses does not already -exist than it is created as part of this service message otherwise the existing +exist then it is created as part of this message otherwise the existing `Delegation` is updated to include the newly received shares. +The delegator receives newly minted shares at the current exchange rate. +The exchange rate is the number of existing shares in the validator divided by +the number of currently delegated tokens. + +TODO: Explain subtractTokens. + ## Msg/Undelegate The `Msg/Undelegate` service message allows delegators to undelegate their tokens from diff --git a/x/staking/spec/08_params.md b/x/staking/spec/08_params.md index 3d87879e18a0..8d78efa5c51a 100644 --- a/x/staking/spec/08_params.md +++ b/x/staking/spec/08_params.md @@ -12,4 +12,4 @@ The staking module contains the following parameters: | MaxValidators | uint16 | 100 | | KeyMaxEntries | uint16 | 7 | | HistoricalEntries | uint16 | 3 | -| BondDenom | string | "uatom" | +| BondDenom | string | "stake" | From a4998f349bd99dc3ef14fe7498018e2ed65c32ff Mon Sep 17 00:00:00 2001 From: hjort <> Date: Tue, 9 Feb 2021 14:22:57 +0100 Subject: [PATCH 03/49] Create a sequence diagram of a (fresh) delegation --- x/staking/keeper/delegation_seq.puml | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 x/staking/keeper/delegation_seq.puml diff --git a/x/staking/keeper/delegation_seq.puml b/x/staking/keeper/delegation_seq.puml new file mode 100644 index 000000000000..87c7be974054 --- /dev/null +++ b/x/staking/keeper/delegation_seq.puml @@ -0,0 +1,63 @@ +@startuml +'https://plantuml.com/sequence-diagram + +title: Delegating (currently undelegated funds delegator) +autonumber + +actor User +User -> SDK : Delegate +SDK -> "handler (staking)": MsgDelegate(Context, Msg(DelegatorAddress, ValidatorAddress, Amount)) +"handler (staking)" -> "msgServer (staking)" : Delegate(Context, Msg) +"msgServer (staking)" -> "msgServer (staking)" : Check validator address is valid. +"msgServer (staking)" -> "msgServer (staking)" : Check correct staking denomination +participant "keeper (staking)" as keeper +"msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator) + + group staking module + alt perform a new delegation + keeper -> validator : Check exchange rate valid + keeper <-- validator : + keeper -> keeper : delegation := create delegation object + keeper -> keeper : Perform a new delegation + + + keeper -> keeper : BeforeDelegationCreated hook + note left: Calls IncrementValidatorPeriod (Used to calculate distribution) \nTODO?: Document deeper? keeper/validator.go + + keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule + keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** + DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake + DelegateCoinsFromAccountToModule -> "func:DelegateCoins" as DelegateCoins ** + DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated + DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) + DelegateCoins --> DelegateCoins : Transfer tokens to staker. + DelegateCoins --> DelegateCoinsFromAccountToModule : nil + destroy DelegateCoins + keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil + destroy DelegateCoinsFromAccountToModule + keeper <-- keeper.bankKeeper : nil (success) + keeper -> validator : AddTokensFromDel + validator -> validator : calculate number of shares to issue + note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) + + database store + + validator -> store : add delegated tokens to validator + validator -> store : update validator's PowerIndex back to power index + note left : TODO?: staking/types/keys.go, line 72, GetValidatorsByPowerIndexKey\nDocument how a validator's power index is calculated, and kept up to date. + keeper -> store : update the delegation object describing this delegation + keeper -> keeper : AfterDelegationModified hook + <-- keeper : newShares (ignored by Delegate function) + note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. + end + end + +"msgServer (staking)" <-- keeper : _, err +"msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress) +"msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress) +"msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom) +"handler (staking)" <-- "msgServer (staking)" : res := MsgDelegateResponse{} (empty struct) +SDK <-- "handler (staking)": return (Context, res, err) + +@enduml + From 73c21a855033cc791311305a13c205775b6e7466 Mon Sep 17 00:00:00 2001 From: hjort <> Date: Tue, 9 Feb 2021 14:24:28 +0100 Subject: [PATCH 04/49] Misc notes, not yet decided where to put them --- x/staking/spec/00_spec.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 x/staking/spec/00_spec.md diff --git a/x/staking/spec/00_spec.md b/x/staking/spec/00_spec.md new file mode 100644 index 000000000000..5f94ddfa85dc --- /dev/null +++ b/x/staking/spec/00_spec.md @@ -0,0 +1,16 @@ +# Validator tokens and Consensus Power + +Total consensus power of a delegator can be calculated from the number of validator tokens they hold, and vice versa. +The equation is as follows: + +``` +tokens = consensus_power * power_reduction +``` + +`power_reduction` is a constant parameter set to `10**6` by default. + +TODO: Is consensus power a network-wide measure or per validator? + +# Staker vs Delegator vs Validator +The Staker and Delegator are actual EOAs. +The Validator is an internal concept (with an address), controlled by the staker. \ No newline at end of file From 8bcf73a0043bf0856951d7cc20b2053def0cfcc8 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 10 Feb 2021 14:44:36 +0100 Subject: [PATCH 05/49] Description of the shares abstraction in validators --- x/staking/spec/00_spec.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/x/staking/spec/00_spec.md b/x/staking/spec/00_spec.md index 5f94ddfa85dc..86e847c006f7 100644 --- a/x/staking/spec/00_spec.md +++ b/x/staking/spec/00_spec.md @@ -13,4 +13,22 @@ TODO: Is consensus power a network-wide measure or per validator? # Staker vs Delegator vs Validator The Staker and Delegator are actual EOAs. -The Validator is an internal concept (with an address), controlled by the staker. \ No newline at end of file +The Validator is an internal concept (with an address), controlled by the staker. + +# The Share Abstraction + +At any given point in time, each validator has a number of tokens, `T`, and has a number of shares issued, `S`. +Each delegator, `i`, holds a number of shares, `S_i`. +The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes. + +The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. +So delegator `i` is entitled to `T * S_i / S` of the validator's tokens. + +When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. +So when delegator `j` delegates `T_j` tokens, they receive `S_j = S * T_j / T` shares. +The total number of tokens is now `T + T_j`, and the total number of shares is `S + S_j`. +`j`s proportion of the shares is the same as their proportion of the total tokens contributed: `(S + S_j) / S = (T + T_j) / T`. + +A special case is the initial delegation, when `T = 0` and `S = 0`, so `T_j / T` is undefined. +For the initial delegation, delegator `j` who delegates `T_j` tokens receive `S_j = T_j` shares. +So a validator that hasn't received any rewards and has not been slashed will have `T = S`. \ No newline at end of file From b476faf68db4c329ae697c125a5bb5ea8464265f Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 11 Feb 2021 15:21:50 +0100 Subject: [PATCH 06/49] Model all keeper dependencies and move the UML file to docs --- .../keeper_dependencies.puml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) rename staking_system.puml => docs/keeper_dependencies.puml (54%) diff --git a/staking_system.puml b/docs/keeper_dependencies.puml similarity index 54% rename from staking_system.puml rename to docs/keeper_dependencies.puml index cf9d77a7cf55..57920012912c 100644 --- a/staking_system.puml +++ b/docs/keeper_dependencies.puml @@ -1,12 +1,28 @@ @startuml 'https://plantuml.com/class-diagram +title: The dependencies between Keepers (Feb 2021) + abstract class Staking abstract class Distribution abstract class Slashing abstract class Evidence abstract class Bank -abstract class Auth +abstract class "Auth/Account" as Auth +abstract class Capability +abstract class Crisis +abstract class Gov +abstract class Mint +abstract class Upgrade + +Staking <-- Mint +Bank <-- Mint + +Staking <|-- Gov +Bank <|-- Gov +Auth <|-- Gov + +Auth <|-- Bank Bank <|-- Distribution Auth <|-- Distribution From 151a4a930e41deca39b14f46cb563e56e84ef9fd Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 11 Feb 2021 15:22:06 +0100 Subject: [PATCH 07/49] Move and rename delegation sequence diagram --- .../{keeper/delegation_seq.puml => spec/delegation_sequence.puml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename x/staking/{keeper/delegation_seq.puml => spec/delegation_sequence.puml} (100%) diff --git a/x/staking/keeper/delegation_seq.puml b/x/staking/spec/delegation_sequence.puml similarity index 100% rename from x/staking/keeper/delegation_seq.puml rename to x/staking/spec/delegation_sequence.puml From 11e1946eede91fab0f935674099e31b34a93c609 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 11 Feb 2021 15:29:00 +0100 Subject: [PATCH 08/49] Move shares description --- x/staking/spec/00_spec.md | 17 ----------------- x/staking/spec/02_state_transitions.md | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/x/staking/spec/00_spec.md b/x/staking/spec/00_spec.md index 86e847c006f7..04eab5fa5b46 100644 --- a/x/staking/spec/00_spec.md +++ b/x/staking/spec/00_spec.md @@ -15,20 +15,3 @@ TODO: Is consensus power a network-wide measure or per validator? The Staker and Delegator are actual EOAs. The Validator is an internal concept (with an address), controlled by the staker. -# The Share Abstraction - -At any given point in time, each validator has a number of tokens, `T`, and has a number of shares issued, `S`. -Each delegator, `i`, holds a number of shares, `S_i`. -The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes. - -The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. -So delegator `i` is entitled to `T * S_i / S` of the validator's tokens. - -When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. -So when delegator `j` delegates `T_j` tokens, they receive `S_j = S * T_j / T` shares. -The total number of tokens is now `T + T_j`, and the total number of shares is `S + S_j`. -`j`s proportion of the shares is the same as their proportion of the total tokens contributed: `(S + S_j) / S = (T + T_j) / T`. - -A special case is the initial delegation, when `T = 0` and `S = 0`, so `T_j / T` is undefined. -For the initial delegation, delegator `j` who delegates `T_j` tokens receive `S_j = T_j` shares. -So a validator that hasn't received any rewards and has not been slashed will have `T = S`. \ No newline at end of file diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index 9e245719cc24..bff15575c226 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -139,3 +139,21 @@ When a validator is slashed, so are all redelegations from the validator that be infraction. Redelegations are slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to prevent a resulting negative balance. Mature redelegations are not slashed. + +## How Shares are calculated + +At any given point in time, each validator has a number of tokens, `T`, and has a number of shares issued, `S`. +Each delegator, `i`, holds a number of shares, `S_i`. +The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes. + +The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. +So delegator `i` is entitled to `T * S_i / S` of the validator's tokens. + +When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. +So when delegator `j` delegates `T_j` tokens, they receive `S_j = S * T_j / T` shares. +The total number of tokens is now `T + T_j`, and the total number of shares is `S + S_j`. +`j`s proportion of the shares is the same as their proportion of the total tokens contributed: `(S + S_j) / S = (T + T_j) / T`. + +A special case is the initial delegation, when `T = 0` and `S = 0`, so `T_j / T` is undefined. +For the initial delegation, delegator `j` who delegates `T_j` tokens receive `S_j = T_j` shares. +So a validator that hasn't received any rewards and has not been slashed will have `T = S`. From 89b5a8ab99da9f00e2ed65e28b141c1a0f2ff7ec Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 11 Feb 2021 15:30:20 +0100 Subject: [PATCH 09/49] Remove TODO --- x/staking/spec/03_messages.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index 7a5c268111c0..6efef43cf621 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -74,8 +74,6 @@ The delegator receives newly minted shares at the current exchange rate. The exchange rate is the number of existing shares in the validator divided by the number of currently delegated tokens. -TODO: Explain subtractTokens. - ## Msg/Undelegate The `Msg/Undelegate` service message allows delegators to undelegate their tokens from From d221b6f2f034dbe84f22e931028a98c2304a410f Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 12 Feb 2021 15:24:19 +0100 Subject: [PATCH 10/49] Diagram touch-ups --- x/staking/spec/delegation_sequence.puml | 82 +++++++++++++------------ 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 87c7be974054..1e289236f29f 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -13,46 +13,48 @@ SDK -> "handler (staking)": MsgDelegate(Context, Msg(DelegatorAddress, Validat participant "keeper (staking)" as keeper "msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator) - group staking module - alt perform a new delegation - keeper -> validator : Check exchange rate valid - keeper <-- validator : - keeper -> keeper : delegation := create delegation object - keeper -> keeper : Perform a new delegation - - - keeper -> keeper : BeforeDelegationCreated hook - note left: Calls IncrementValidatorPeriod (Used to calculate distribution) \nTODO?: Document deeper? keeper/validator.go - - keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule - keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** - DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake - DelegateCoinsFromAccountToModule -> "func:DelegateCoins" as DelegateCoins ** - DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated - DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) - DelegateCoins --> DelegateCoins : Transfer tokens to staker. - DelegateCoins --> DelegateCoinsFromAccountToModule : nil - destroy DelegateCoins - keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil - destroy DelegateCoinsFromAccountToModule - keeper <-- keeper.bankKeeper : nil (success) - keeper -> validator : AddTokensFromDel - validator -> validator : calculate number of shares to issue - note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) - - database store - - validator -> store : add delegated tokens to validator - validator -> store : update validator's PowerIndex back to power index - note left : TODO?: staking/types/keys.go, line 72, GetValidatorsByPowerIndexKey\nDocument how a validator's power index is calculated, and kept up to date. - keeper -> store : update the delegation object describing this delegation - keeper -> keeper : AfterDelegationModified hook - <-- keeper : newShares (ignored by Delegate function) - note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. - end - end - -"msgServer (staking)" <-- keeper : _, err + keeper -> validator : Check exchange rate valid + keeper <-- validator : +alt perform a new delegation + keeper -> keeper : delegation := create delegation object +end + +keeper -> keeper : BeforeDelegationCreated hook +note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go + +keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule +keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** +note left : TODO this should interact with the store, too +DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake +DelegateCoinsFromAccountToModule -> "func:DelegateCoins" as DelegateCoins ** +DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated +DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) +DelegateCoins --> store : Transfer tokens to staker. +DelegateCoins --> DelegateCoinsFromAccountToModule : nil +destroy DelegateCoins +keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil +destroy DelegateCoinsFromAccountToModule +keeper <-- keeper.bankKeeper : nil (success) +keeper -> validator : AddTokensFromDel +validator -> validator : calculate number of shares to issue +note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) + +database store + +validator -> validator : add delegated tokens to validator +keeper <-- validator : validator, addedShares +keeper -> store : update validator state +keeper -> keeper: calculate new validator's power +keeper -> store : update validator's power in power index +note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. +alt redelegation + keeper -> store : update the delegation object describing this delegation. +end +keeper -> keeper : AfterDelegationModified hook +note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. +"msgServer (staking)" <-- keeper : newShares (ignored by Delegate function) + + "msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress) "msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress) "msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom) From d151fa1879ff7ecc82a1bb3dac5beb849caf2af9 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 12 Feb 2021 16:57:59 +0100 Subject: [PATCH 11/49] Add how consensus power is calculated --- x/staking/spec/delegation_sequence.puml | 1 + 1 file changed, 1 insertion(+) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 1e289236f29f..792eadb7b43c 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -45,6 +45,7 @@ validator -> validator : add delegated tokens to validator keeper <-- validator : validator, addedShares keeper -> store : update validator state keeper -> keeper: calculate new validator's power +note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18) keeper -> store : update validator's power in power index note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. alt redelegation From d791e124a9d107b03faa227a2770b19b523b18ff Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 12 Feb 2021 16:59:30 +0100 Subject: [PATCH 12/49] remove temp file --- x/staking/spec/00_spec.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 x/staking/spec/00_spec.md diff --git a/x/staking/spec/00_spec.md b/x/staking/spec/00_spec.md deleted file mode 100644 index 04eab5fa5b46..000000000000 --- a/x/staking/spec/00_spec.md +++ /dev/null @@ -1,17 +0,0 @@ -# Validator tokens and Consensus Power - -Total consensus power of a delegator can be calculated from the number of validator tokens they hold, and vice versa. -The equation is as follows: - -``` -tokens = consensus_power * power_reduction -``` - -`power_reduction` is a constant parameter set to `10**6` by default. - -TODO: Is consensus power a network-wide measure or per validator? - -# Staker vs Delegator vs Validator -The Staker and Delegator are actual EOAs. -The Validator is an internal concept (with an address), controlled by the staker. - From f6f81616c01f8413c525ca69f41e72f5e371cae7 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 12 Feb 2021 18:02:13 +0100 Subject: [PATCH 13/49] Diagram improvements --- docs/keeper_dependencies.puml | 4 ++-- x/staking/spec/delegation_sequence.puml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/keeper_dependencies.puml b/docs/keeper_dependencies.puml index 57920012912c..d0d637c7fa75 100644 --- a/docs/keeper_dependencies.puml +++ b/docs/keeper_dependencies.puml @@ -15,8 +15,8 @@ abstract class Gov abstract class Mint abstract class Upgrade -Staking <-- Mint -Bank <-- Mint +Staking <|-- Mint +Bank <|-- Mint Staking <|-- Gov Bank <|-- Gov diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 792eadb7b43c..962f1d4f0651 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -6,7 +6,7 @@ autonumber actor User User -> SDK : Delegate -SDK -> "handler (staking)": MsgDelegate(Context, Msg(DelegatorAddress, ValidatorAddress, Amount)) +SDK -> "handler (staking)": MsgDelegate(Context, \n Msg(DelegatorAddress, ValidatorAddress, Amount)) "handler (staking)" -> "msgServer (staking)" : Delegate(Context, Msg) "msgServer (staking)" -> "msgServer (staking)" : Check validator address is valid. "msgServer (staking)" -> "msgServer (staking)" : Check correct staking denomination @@ -24,7 +24,6 @@ note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in ke keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** -note left : TODO this should interact with the store, too DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake DelegateCoinsFromAccountToModule -> "func:DelegateCoins" as DelegateCoins ** DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated @@ -39,6 +38,7 @@ keeper -> validator : AddTokensFromDel validator -> validator : calculate number of shares to issue note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) +'TODO: Find right keyword. database store validator -> validator : add delegated tokens to validator @@ -59,7 +59,7 @@ note left: Calls initializeDelegation\nStore the previous period\nCalculate the "msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress) "msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress) "msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom) -"handler (staking)" <-- "msgServer (staking)" : res := MsgDelegateResponse{} (empty struct) +"handler (staking)" <-- "msgServer (staking)" : res := MsgDelegateResponse{}\n(empty struct) SDK <-- "handler (staking)": return (Context, res, err) @enduml From 92050cda78d7a0fd3c5aa8a0c4043f5ca26cf26d Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 12 Feb 2021 18:04:09 +0100 Subject: [PATCH 14/49] Describe slashing in more detail --- x/staking/spec/02_state_transitions.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index bff15575c226..4a69769b95dd 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -105,6 +105,9 @@ Redelegations affect the delegation, source and destination validators. is `Bonded`, transfer the newly delegated tokens from the `NotBondedPool` to the `BondedPool` `ModuleAccount` - record the token amount in an new entry in the relevant `Redelegation` +From when a redelegation begins until it completes, the delegator is in a state of "pseudo-unbonding", and can still be +slashed for infractions that occured before the redelegation began. + ### Complete Redelegation When a redelegations complete the following occurs: @@ -119,13 +122,17 @@ When a Validator is slashed, the following occurs: - The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) \* `TokensFromConsensusPower`, the total number of tokens bonded to the validator at the time of the infraction. -- Every unbonding delegation and redelegation from the validator are slashed by the `slashFactor` - percentage of the initialBalance. +- Every unbonding delegation and pseudo-unbonding redelegation such that the infraction occured before the unbonding or + redelegation began from the validator are slashed by the `slashFactor` percentage of the initialBalance. - Each amount slashed from redelegations and unbonding delegations is subtracted from the total slash amount. - The `remaingSlashAmount` is then slashed from the validator's tokens in the `BondedPool` or `NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. +In the case of a slash due to any infraction that requires evidence to submitted (for example double-sign), the slash +occurs at the block where the evidence is included, not at the block where the infraction occured. +Put otherwise, validators are not slashed retroactively, only when they are caught. + ### Slash Unbonding Delegation When a validator is slashed, so are those unbonding delegations from the validator that began unbonding @@ -137,8 +144,10 @@ delegation and is capped to prevent a resulting negative balance. Completed (or When a validator is slashed, so are all redelegations from the validator that began after the infraction. Redelegations are slashed by `slashFactor`. +Redelegations that began before the infraction are not slashed. The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to -prevent a resulting negative balance. Mature redelegations are not slashed. +prevent a resulting negative balance. +Mature redelegations (that have completed pseudo-unbonding) are not slashed. ## How Shares are calculated From f3d5e8f266bde8f0f5566b81e9eb8f963f8fe634 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Tue, 16 Feb 2021 16:41:21 +0100 Subject: [PATCH 15/49] Describe redelegation --- .../spec/begin_redelegation_sequence.puml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 x/staking/spec/begin_redelegation_sequence.puml diff --git a/x/staking/spec/begin_redelegation_sequence.puml b/x/staking/spec/begin_redelegation_sequence.puml new file mode 100644 index 000000000000..123dcfa8c848 --- /dev/null +++ b/x/staking/spec/begin_redelegation_sequence.puml @@ -0,0 +1,51 @@ +@startuml +'https://plantuml.com/sequence-diagram + +title: Delegating (currently undelegated funds delegator) +autonumber + +msgServer -> keeper : BeginRedelegation(delAddr, valSrcAddr, valDstAddr, sharesAmount) +participant "keeper (staking)" as keeper +keeper -> keeper : get number of sharew +note left: If the delegator has more shares than the total shares in the validator\n(due to rounding errors), then just withdraw the max number of shares. +keeper -> keeper : check the redelegation uses correct denom + +alt valSrcAddr == valDstAddr + keeper --> msgServer : error +end +alt transitive redelegation + keeper --> msgServer : error +end +alt already has max redelegations + keeper --> msgServer : error + note left : this is the number of redelegations for a specific (del, valSrc, valDst) triple\ndefault : 7 +end + + +keeper -> keeper : Unbond(del, valSrc) returns returnAmount +... +note left : TODO: Describe unbond + +alt returnAmount is zero +keeper -> msgServer : error +end + +keeper -> keeper : Delegate(del, returnAmount, status := valSrc.status, valDst, subtractAccount := false) +note left : TODO: explore different statuses in Delegate +... + +alt validator is unbonded + keeper -> msgServer : current time +end + +alt unbonding not complete, or just started + database store + keeper -> store : create redelegation object + keeper -> store : insert redelegation in queue, to be processed at the appropriate time +end + +msgServer <-- keeper : completion time of the redelegation +msgServer -> msgServer : emit event: delegator, valSrc, valSrc,\nsharesAmount, completionTime + +@enduml + From e717f07965faab26dc0d60d5a1d84f84fc1dea9a Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Tue, 16 Feb 2021 16:41:28 +0100 Subject: [PATCH 16/49] Describe unbonding --- x/staking/spec/unbond_sequence.puml | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 x/staking/spec/unbond_sequence.puml diff --git a/x/staking/spec/unbond_sequence.puml b/x/staking/spec/unbond_sequence.puml new file mode 100644 index 000000000000..8988b5000295 --- /dev/null +++ b/x/staking/spec/unbond_sequence.puml @@ -0,0 +1,53 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount) + +keeper -> keeper : calculate number of shares the tokenAmount represents + +alt wrong denom + msgServer <-- keeper : error +end + +group Unbond(delAddr, valAddr, shares) + keeper -> keeper: BeforeDelegationSharesModified hook + alt no such delegation + keeper --> msgServer : error + end + alt not enough shares + keeper --> msgServer : error + end + alt delegator is the operator of the validator\nand validator is not already jailed\nand unbonding would put self-delegation under min threshold + keeper -> keeper : jail the validator, but proceed with unbonding + note left : Default min delegation threshold : 1 share + end + + database store + + alt complete unbonding, all shares removed + keeper -> store : remove delegation object + end + + alt there are still shares delegated (not a complete undbonding) + keeper -> store : update delegation object + keeper -> keeper : AfterDelegationModified hook + end + + keeper -> store : update validator power index + keeper -> store : update validator information (including token amount) + + alt validator status is "unbonded" and it has no more tokens + keeper -> store : delete the validator + note right : otherwise, do this in EndBlock once validator is unbonded + end +end + +alt validator is bonded + keeper -> bankKeeper : send tokens from bonded pool to not bonded pool +end + +msgServer -> msgServer : emit event : EventTypeUnbond(delAddr, valAddr, tokenAmount, completion time) + +@enduml \ No newline at end of file From 6f9c7a7864c4b9f861974e5a806c99843c0a5954 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 17 Feb 2021 17:06:47 +0100 Subject: [PATCH 17/49] Delegation updates --- x/staking/spec/delegation_sequence.puml | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 962f1d4f0651..26e30ac85350 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -4,23 +4,34 @@ title: Delegating (currently undelegated funds delegator) autonumber -actor User -User -> SDK : Delegate -SDK -> "handler (staking)": MsgDelegate(Context, \n Msg(DelegatorAddress, ValidatorAddress, Amount)) -"handler (staking)" -> "msgServer (staking)" : Delegate(Context, Msg) -"msgServer (staking)" -> "msgServer (staking)" : Check validator address is valid. -"msgServer (staking)" -> "msgServer (staking)" : Check correct staking denomination +participant "msgServer (staking)" participant "keeper (staking)" as keeper -"msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator) +"msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator, tokenSrc := Unbonded) + +alt exchange rate is invalid (tokens in validator is 0) + keeper --> "msgServer (staking)" : error +end - keeper -> validator : Check exchange rate valid - keeper <-- validator : alt perform a new delegation keeper -> keeper : delegation := create delegation object end -keeper -> keeper : BeforeDelegationCreated hook -note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go +alt new delegation + keeper -> keeper : BeforeDelegationCreated hook + note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go +end +alt delegation exists, more tokens being added + keeper -> keeper : BeforeDelegationModified hook + note left: withdraw current delegation rewards (and increment period) +end + +alt delegating from an account (subtractTokens == true) + alt validator is currently bonded + keeper -> keeper : sendName := BondedPool + end + alt validator is currently bonded + keeper -> keeper : sendName := NotBondedPool + end keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** @@ -48,9 +59,8 @@ keeper -> keeper: calculate new validator's power note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18) keeper -> store : update validator's power in power index note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. -alt redelegation - keeper -> store : update the delegation object describing this delegation. end + keeper -> keeper : AfterDelegationModified hook note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. "msgServer (staking)" <-- keeper : newShares (ignored by Delegate function) From c878b2343a0c81386ccce4866f8fc1b8a76933ec Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 17 Feb 2021 17:06:54 +0100 Subject: [PATCH 18/49] Delegation updates --- x/staking/spec/03_messages.md | 1 + 1 file changed, 1 insertion(+) diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index 6efef43cf621..d0f059ecf6b6 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -9,6 +9,7 @@ In this section we describe the processing of the staking messages and the corre ## Msg/CreateValidator A validator is created using the `Msg/CreateValidator` service message. +The validator must be created with an initial delegation from the operator. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L16-L17 From c42bf871de1dd01ace8ba2a2e7d52f8a40fb0915 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 17 Feb 2021 17:07:14 +0100 Subject: [PATCH 19/49] Make a diagram describing overall transaction flow --- docs/transaction_flow.puml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/transaction_flow.puml diff --git a/docs/transaction_flow.puml b/docs/transaction_flow.puml new file mode 100644 index 000000000000..0d0ff82aabd3 --- /dev/null +++ b/docs/transaction_flow.puml @@ -0,0 +1,22 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +actor User +User -> baseApp : Transaction Type +baseApp -> router : Route(ctx, msgRoute) +router --> baseApp : handler +baseApp -> handler: Msg(Context, Msg(...)) +handler -> msgServer : (Context, Msg) +alt addresses invalid, denominations wrong, etc. +msgServer --> handler : error +end +msgServer -> keeper : perform action, update context +keeper --> msgServer : results, error code +msgServer -> Context.EventManager : Emit relevant events +msgServer -> msgServer : maybe wrap results in more structure +msgServer --> handler : result, error code +baseApp <-- handler : results, error code + +@enduml \ No newline at end of file From ed32e4d9ddba5bf089f108375666274d538b389c Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 17 Feb 2021 18:43:43 +0100 Subject: [PATCH 20/49] Add delegation flows for the events of tokens being bonded/unbonding/etc. --- x/staking/spec/delegation_sequence.puml | 70 +++++++++++++++++-------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 26e30ac85350..de3d1943aa84 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -6,6 +6,17 @@ autonumber participant "msgServer (staking)" participant "keeper (staking)" as keeper +participant validator +participant keeper.bankKeeper +participant vestingAccount +participant "func:SendCoins" as SendCoins +participant ctx.EventManager +participant "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule +participant "func:DelegateCoins" as DelegateCoins +participant trackDelegation + +database store + "msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator, tokenSrc := Unbonded) alt exchange rate is invalid (tokens in validator is 0) @@ -26,32 +37,52 @@ alt delegation exists, more tokens being added end alt delegating from an account (subtractTokens == true) + keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule + keeper.bankKeeper -> DelegateCoinsFromAccountToModule ** + DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake + DelegateCoinsFromAccountToModule -> DelegateCoins ** + + DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated + DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) alt validator is currently bonded - keeper -> keeper : sendName := BondedPool + DelegateCoins --> store : Transfer tokens from delegator to BondedTokensPool. end - alt validator is currently bonded - keeper -> keeper : sendName := NotBondedPool + alt validator is currently unbonded or unbonding + DelegateCoins --> store : Transfer tokens from delegator to NotBondedTokensPool. + end + DelegateCoins -> trackDelegation ** : + alt delegator is a vesting account + trackDelegation -> vestingAccount : keep track of this delegation end + DelegateCoins <-- trackDelegation : nil + destroy trackDelegation + DelegateCoinsFromAccountToModule <-- DelegateCoins : nil + destroy DelegateCoins + keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil + destroy DelegateCoinsFromAccountToModule + keeper <-- keeper.bankKeeper : nil (success) +end + +alt moving tokens between pools (subtractTokens == false) + alt delegator tokens are not bonded but validator is bonded + keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(notBondedPool, bondedPool, coins) + end + alt delegator tokens are bonded but validator is not bonded + keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(bondedPool, notBondedPool, coins) + end + keeper.bankKeeper -> SendCoins + SendCoins -> ctx.EventManager : Emit TransferEvent(to, from, amount) + alt amount of spendable (balance - locked) coins too low + keeper.bankKeeper <-- SendCoins : error + end + SendCoins -> store : subtract balance from sender + SendCoins -> store : add balance to recipient +end -keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule -keeper.bankKeeper -> "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule ** -DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake -DelegateCoinsFromAccountToModule -> "func:DelegateCoins" as DelegateCoins ** -DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated -DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) -DelegateCoins --> store : Transfer tokens to staker. -DelegateCoins --> DelegateCoinsFromAccountToModule : nil -destroy DelegateCoins -keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil -destroy DelegateCoinsFromAccountToModule -keeper <-- keeper.bankKeeper : nil (success) keeper -> validator : AddTokensFromDel validator -> validator : calculate number of shares to issue note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens) -'TODO: Find right keyword. -database store - validator -> validator : add delegated tokens to validator keeper <-- validator : validator, addedShares keeper -> store : update validator state @@ -59,7 +90,6 @@ keeper -> keeper: calculate new validator's power note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18) keeper -> store : update validator's power in power index note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. -end keeper -> keeper : AfterDelegationModified hook note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. @@ -69,8 +99,6 @@ note left: Calls initializeDelegation\nStore the previous period\nCalculate the "msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress) "msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress) "msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom) -"handler (staking)" <-- "msgServer (staking)" : res := MsgDelegateResponse{}\n(empty struct) -SDK <-- "handler (staking)": return (Context, res, err) @enduml From 30c39335f4b9557bc6d4c5ca2d897656f5540708 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 18 Feb 2021 16:39:52 +0100 Subject: [PATCH 21/49] Grammar fix --- x/staking/spec/01_state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index e090acb01541..6065661625dc 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -34,7 +34,7 @@ Validators can have one of three statuses during the period of time that the tokens were bonded. - `Unbonding`: When a validator leaves the active set, either by choice or due to slashing or tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime - before moving receiving their tokens to their accounts from the `BondedPool`. + before moving their tokens to their accounts from the `BondedPool`. Validators objects should be primarily stored and accessed by the `OperatorAddr`, an SDK validator address for the operator of the validator. Two From 02dbc236b549d557be1e30a26365f537435d8675 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 25 Feb 2021 14:02:28 +0100 Subject: [PATCH 22/49] Diagram updates: distinguish alts, remove numbering. --- x/staking/spec/delegation_sequence.puml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index de3d1943aa84..931be0e733c5 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -2,7 +2,6 @@ 'https://plantuml.com/sequence-diagram title: Delegating (currently undelegated funds delegator) -autonumber participant "msgServer (staking)" participant "keeper (staking)" as keeper @@ -25,13 +24,9 @@ end alt perform a new delegation keeper -> keeper : delegation := create delegation object -end - -alt new delegation keeper -> keeper : BeforeDelegationCreated hook note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go -end -alt delegation exists, more tokens being added +else delegation exists, more tokens being added keeper -> keeper : BeforeDelegationModified hook note left: withdraw current delegation rewards (and increment period) end @@ -61,13 +56,10 @@ alt delegating from an account (subtractTokens == true) keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil destroy DelegateCoinsFromAccountToModule keeper <-- keeper.bankKeeper : nil (success) -end - -alt moving tokens between pools (subtractTokens == false) +else moving tokens between pools (subtractTokens == false) alt delegator tokens are not bonded but validator is bonded keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(notBondedPool, bondedPool, coins) - end - alt delegator tokens are bonded but validator is not bonded + else delegator tokens are bonded but validator is not bonded keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(bondedPool, notBondedPool, coins) end keeper.bankKeeper -> SendCoins From ca7e6d6733e7a9df3b02577653de2b7cefaa9e48 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 25 Feb 2021 14:27:58 +0100 Subject: [PATCH 23/49] Use groups instead of "func:" participants --- x/staking/spec/delegation_sequence.puml | 60 ++++++++++++------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 931be0e733c5..615ceea2e362 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -8,11 +8,7 @@ participant "keeper (staking)" as keeper participant validator participant keeper.bankKeeper participant vestingAccount -participant "func:SendCoins" as SendCoins participant ctx.EventManager -participant "func:DelegateCoinsFromAccountToModule" as DelegateCoinsFromAccountToModule -participant "func:DelegateCoins" as DelegateCoins -participant trackDelegation database store @@ -33,28 +29,28 @@ end alt delegating from an account (subtractTokens == true) keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule - keeper.bankKeeper -> DelegateCoinsFromAccountToModule ** - DelegateCoinsFromAccountToModule --> DelegateCoinsFromAccountToModule : Check recipient has permission to stake - DelegateCoinsFromAccountToModule -> DelegateCoins ** - - DelegateCoins --> DelegateCoins : Check the delegator has enough balances of all tokens delegated - DelegateCoins --> DelegateCoins : Track delegation (register that it exists to keep track of it) - alt validator is currently bonded - DelegateCoins --> store : Transfer tokens from delegator to BondedTokensPool. - end - alt validator is currently unbonded or unbonding - DelegateCoins --> store : Transfer tokens from delegator to NotBondedTokensPool. - end - DelegateCoins -> trackDelegation ** : - alt delegator is a vesting account - trackDelegation -> vestingAccount : keep track of this delegation + group DelegateCoinsFromAccountToModule function + keeper.bankKeeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule + alt recipient does not exist or does not have permission to stake + keeper.bankKeeper -> keeper.bankKeeper : panic + end + keeper.bankKeeper -> keeper.bankKeeper : DelegateCoins + group DelegateCoins function + keeper.bankKeeper --> keeper.bankKeeper : Check the delegator has enough balances of all tokens delegated + keeper.bankKeeper --> keeper.bankKeeper : Track delegation (register that it exists to keep track of it) + alt validator is currently bonded + keeper.bankKeeper --> store : Transfer tokens from delegator to BondedTokensPool. + else validator is currently unbonded or unbonding + keeper.bankKeeper --> store : Transfer tokens from delegator to NotBondedTokensPool. + end + group trackDelegation function + keeper.bankKeeper -> keeper.bankKeeper : trackDelegation + alt delegator is a vesting account + keeper.bankKeeper -> vestingAccount : keep track of this delegation + end + end + end end - DelegateCoins <-- trackDelegation : nil - destroy trackDelegation - DelegateCoinsFromAccountToModule <-- DelegateCoins : nil - destroy DelegateCoins - keeper.bankKeeper <-- DelegateCoinsFromAccountToModule: nil - destroy DelegateCoinsFromAccountToModule keeper <-- keeper.bankKeeper : nil (success) else moving tokens between pools (subtractTokens == false) alt delegator tokens are not bonded but validator is bonded @@ -62,13 +58,15 @@ else moving tokens between pools (subtractTokens == false) else delegator tokens are bonded but validator is not bonded keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(bondedPool, notBondedPool, coins) end - keeper.bankKeeper -> SendCoins - SendCoins -> ctx.EventManager : Emit TransferEvent(to, from, amount) - alt amount of spendable (balance - locked) coins too low - keeper.bankKeeper <-- SendCoins : error + group SendCoins function + keeper.bankKeeper -> keeper.bankKeeper : SendCoins + keeper.bankKeeper -> ctx.EventManager : Emit TransferEvent(to, from, amount) + alt amount of spendable (balance - locked) coins too low + keeper <-- keeper.bankKeeper : error + end + keeper.bankKeeper -> store : subtract balance from sender + keeper.bankKeeper -> store : add balance to recipient end - SendCoins -> store : subtract balance from sender - SendCoins -> store : add balance to recipient end keeper -> validator : AddTokensFromDel From cbbeb3bf31ca0ceb6bb3f2ea99ccb9e8f4444670 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 17:38:12 +0100 Subject: [PATCH 24/49] Remove unused keepers from dependency diagram --- docs/keeper_dependencies.puml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/keeper_dependencies.puml b/docs/keeper_dependencies.puml index d0d637c7fa75..5a80ad9f33d5 100644 --- a/docs/keeper_dependencies.puml +++ b/docs/keeper_dependencies.puml @@ -9,11 +9,8 @@ abstract class Slashing abstract class Evidence abstract class Bank abstract class "Auth/Account" as Auth -abstract class Capability -abstract class Crisis abstract class Gov abstract class Mint -abstract class Upgrade Staking <|-- Mint Bank <|-- Mint @@ -36,4 +33,4 @@ Staking <|-- Slashing Auth <|-- Staking Bank <|-- Staking -@enduml \ No newline at end of file +@enduml From 9e4f11e87b9979bd8f53dbfb3d8722526747986f Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 17:38:47 +0100 Subject: [PATCH 25/49] Add title to unbonding diagram --- x/staking/spec/unbond_sequence.puml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/staking/spec/unbond_sequence.puml b/x/staking/spec/unbond_sequence.puml index 8988b5000295..7852596491f9 100644 --- a/x/staking/spec/unbond_sequence.puml +++ b/x/staking/spec/unbond_sequence.puml @@ -3,6 +3,8 @@ autonumber +title: Unbond message + msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount) keeper -> keeper : calculate number of shares the tokenAmount represents @@ -28,9 +30,7 @@ group Unbond(delAddr, valAddr, shares) alt complete unbonding, all shares removed keeper -> store : remove delegation object - end - - alt there are still shares delegated (not a complete undbonding) + else there are still shares delegated (not a complete undbonding) keeper -> store : update delegation object keeper -> keeper : AfterDelegationModified hook end @@ -50,4 +50,4 @@ end msgServer -> msgServer : emit event : EventTypeUnbond(delAddr, valAddr, tokenAmount, completion time) -@enduml \ No newline at end of file +@enduml From c00da7aabe341204738448cffead75eb7977b1f5 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 17:39:18 +0100 Subject: [PATCH 26/49] Move keeper dependencies --- {docs => x/staking/spec}/keeper_dependencies.puml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {docs => x/staking/spec}/keeper_dependencies.puml (100%) diff --git a/docs/keeper_dependencies.puml b/x/staking/spec/keeper_dependencies.puml similarity index 100% rename from docs/keeper_dependencies.puml rename to x/staking/spec/keeper_dependencies.puml From fb07c0378b113dc1f4f2e7579b05089557e0aa6d Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 13:45:44 +0100 Subject: [PATCH 27/49] small doc updates --- x/staking/spec/02_state_transitions.md | 3 +++ x/staking/spec/05_end_block.md | 2 +- x/staking/spec/endblock.puml | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 x/staking/spec/endblock.puml diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index 4a69769b95dd..93eb4524d934 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -55,6 +55,9 @@ this process may be also be reversed. the following operations occur: - if jailed delete record from `ValidatorByPowerIndex` - if unjailed add record to `ValidatorByPowerIndex` +Jailed validators are not present in any of the following stores: +- the power store (from consensus power to address) + ## Delegations ### Delegate diff --git a/x/staking/spec/05_end_block.md b/x/staking/spec/05_end_block.md index c0777896fbfd..81f4ae9a8997 100644 --- a/x/staking/spec/05_end_block.md +++ b/x/staking/spec/05_end_block.md @@ -41,7 +41,7 @@ When a validator is kicked out of the bonded validator set (either through being jailed, or not having sufficient bonded tokens) it begins the unbonding process along with all its delegations begin unbonding (while still being delegated to this validator). At this point the validator is said to be an -unbonding validator, whereby it will mature to become an "unbonded validator" +"unbonding validator", whereby it will mature to become an "unbonded validator" after the unbonding period has passed. Each block the validator queue is to be checked for mature unbonding validators diff --git a/x/staking/spec/endblock.puml b/x/staking/spec/endblock.puml new file mode 100644 index 000000000000..ac2c2d39134f --- /dev/null +++ b/x/staking/spec/endblock.puml @@ -0,0 +1,11 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml \ No newline at end of file From fd1382ea87022cceb8b93702dcdb64ccbf86ff95 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 13:45:59 +0100 Subject: [PATCH 28/49] remove numbers on sequence diagram --- x/staking/spec/begin_redelegation_sequence.puml | 1 - 1 file changed, 1 deletion(-) diff --git a/x/staking/spec/begin_redelegation_sequence.puml b/x/staking/spec/begin_redelegation_sequence.puml index 123dcfa8c848..8c1dda30f295 100644 --- a/x/staking/spec/begin_redelegation_sequence.puml +++ b/x/staking/spec/begin_redelegation_sequence.puml @@ -2,7 +2,6 @@ 'https://plantuml.com/sequence-diagram title: Delegating (currently undelegated funds delegator) -autonumber msgServer -> keeper : BeginRedelegation(delAddr, valSrcAddr, valDstAddr, sharesAmount) participant "keeper (staking)" as keeper From 48f4d5a678fb10d2fc4d186ced291219b9731243 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 13:46:58 +0100 Subject: [PATCH 29/49] !!!WIP EndBlock --- x/staking/spec/endblock.puml | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/x/staking/spec/endblock.puml b/x/staking/spec/endblock.puml index ac2c2d39134f..c298616cbc9b 100644 --- a/x/staking/spec/endblock.puml +++ b/x/staking/spec/endblock.puml @@ -1,11 +1,30 @@ @startuml 'https://plantuml.com/sequence-diagram -autonumber +participant keeper +database store -Alice -> Bob: Authentication Request -Bob --> Alice: Authentication Response +keeper -> keeper : ApplyAndReturnValidatorSetUpdates +note left : returns a list of `abci.ValidatorUpdate`s +group ApplyAndReturnValidatorSetUpdates + keeper -> keeper : last := map from active validators at the beginning of current block to their power. (getLastValidatorsByAddr) + loop for the `maxValidators` number of validators with power > 0\n(current power, which may have changed during the block) + 'TODO: how are totalPower, amtFromBondedToNotBonded, amtFromNotBondedToBonded used? + alt validator is unbonded or unbonding + keeper -> keeper : bondValidator + note left : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator + group bondValidator + keeper -> keeper + 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 + end + end + keeper -> store : update validator's power in power index (add it if not already present) + end + 'After loop: totalPower = amount of power of the new validator set + ' amtFromNotBondedToBonded = number of previously undonded tokens now bonded + ' amtFromBondedToNotBonded = 0 + keeper -> keeper : noLongerBonded := map validator -> power of all validators that were bonded this block, but won't be next block. + +end -Alice -> Bob: Another authentication Request -Alice <-- Bob: another authentication Response @enduml \ No newline at end of file From 04f6b48356d14872230bc652184ef9bd2fba19fe Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:28:42 +0100 Subject: [PATCH 30/49] Explain "Last"-prefix in storage --- x/staking/spec/01_state.md | 1 + 1 file changed, 1 insertion(+) diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index 66c6c0c5d61c..74061fa46d77 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -7,6 +7,7 @@ order: 1 ## LastTotalPower LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. +Store entries prefixed with "Last" must remain unchanged until EndBlock. - LastTotalPower: `0x12 -> ProtocolBuffer(sdk.Int)` From 5762dad5744fdfc7c6c10fce6fb6ab76198f835e Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:29:24 +0100 Subject: [PATCH 31/49] Remove `panic` step (they are supposed to never happen) --- x/staking/spec/delegation_sequence.puml | 3 --- 1 file changed, 3 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 615ceea2e362..9a99f0b7e5a4 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -31,9 +31,6 @@ alt delegating from an account (subtractTokens == true) keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule group DelegateCoinsFromAccountToModule function keeper.bankKeeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule - alt recipient does not exist or does not have permission to stake - keeper.bankKeeper -> keeper.bankKeeper : panic - end keeper.bankKeeper -> keeper.bankKeeper : DelegateCoins group DelegateCoins function keeper.bankKeeper --> keeper.bankKeeper : Check the delegator has enough balances of all tokens delegated From ea6c9d559c1d71391ec27d79ffcc260f1ce30c3d Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:29:45 +0100 Subject: [PATCH 32/49] EndBlock sequence diagram (with TODOs) --- x/staking/spec/endblock.puml | 30 -------- x/staking/spec/endblock_sequence.puml | 103 ++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 30 deletions(-) delete mode 100644 x/staking/spec/endblock.puml create mode 100644 x/staking/spec/endblock_sequence.puml diff --git a/x/staking/spec/endblock.puml b/x/staking/spec/endblock.puml deleted file mode 100644 index c298616cbc9b..000000000000 --- a/x/staking/spec/endblock.puml +++ /dev/null @@ -1,30 +0,0 @@ -@startuml -'https://plantuml.com/sequence-diagram - -participant keeper -database store - -keeper -> keeper : ApplyAndReturnValidatorSetUpdates -note left : returns a list of `abci.ValidatorUpdate`s -group ApplyAndReturnValidatorSetUpdates - keeper -> keeper : last := map from active validators at the beginning of current block to their power. (getLastValidatorsByAddr) - loop for the `maxValidators` number of validators with power > 0\n(current power, which may have changed during the block) - 'TODO: how are totalPower, amtFromBondedToNotBonded, amtFromNotBondedToBonded used? - alt validator is unbonded or unbonding - keeper -> keeper : bondValidator - note left : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator - group bondValidator - keeper -> keeper - 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 - end - end - keeper -> store : update validator's power in power index (add it if not already present) - end - 'After loop: totalPower = amount of power of the new validator set - ' amtFromNotBondedToBonded = number of previously undonded tokens now bonded - ' amtFromBondedToNotBonded = 0 - keeper -> keeper : noLongerBonded := map validator -> power of all validators that were bonded this block, but won't be next block. - -end - -@enduml \ No newline at end of file diff --git a/x/staking/spec/endblock_sequence.puml b/x/staking/spec/endblock_sequence.puml new file mode 100644 index 000000000000..b0f4499ff859 --- /dev/null +++ b/x/staking/spec/endblock_sequence.puml @@ -0,0 +1,103 @@ +@startuml +'https://plantuml.com/sequence-diagram + +title: EndBlock\nAt this point the + +participant keeper +participant keeper.bankKeeper +participant ctx.EventManager +database store + +keeper -> keeper : BlockValidatorUpdates +group BlockValidatorUpdates + note left : returns `updates`, a list of `abci.ValidatorUpdate`s + keeper -> keeper : ApplyAndReturnValidatorSetUpdates + group ApplyAndReturnValidatorSetUpdates + keeper -> store : get the validators the set of validators for the beginning of the current block and their power. + keeper <-- store : `last` + keeper -> store : get the validators sorted by their current power (possibly updated in the block), highest to least. + keeper <-- store : `iterator` + loop for the first `maxValidators` validators in `iterator` + 'If there are less than `maxValidators`, then jut loop over all of them. + '`maxValidators` is just an upper bound. + alt validator is unbonded or unbonding + keeper -> keeper : bondValidator(validator) + note left : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator + group bondValidator + keeper -> keeper + 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 + end + end + alt if validator power has changed + keeper -> store : update validator's power in power index (add it if not already present) + keeper -> keeper : append validator and its new power to `updates` + end + keeper -> keeper : delete validator from `last` map + end + 'After loop: totalPower = amount of power of the new validator set + ' amtFromNotBondedToBonded = number of previously not bonded tokens now bonded + ' amtFromBondedToNotBonded = 0 + ' last = all validators at the beginning of the block + keeper -> keeper : noLongerBonded := `last` sorted by address + note left : `last` now contains exactly the validators of the current block\nthat will not be validators in the next block. + loop for validator in noLongerBonded + keeper -> keeper : bondedToUnbonding(validator) + keeper -> store : delete validator from power index + keeper -> keeper : append validator and its new power (0) to `updates` + end + 'After loop: amtFromBondedToNotBonded = number of previously bonded tokens now not bonded + alt newly bonded tokens > newly not bonded tokens + keeper -> keeper.bankKeeper : sendCoinsFromModuleToModule(NotBondedPool, BondedPool, diff) + else newly bonded tokens < newly not bonded tokens + keeper -> keeper.bankKeeper : sendCoinsFromModuleToModule(BondedPool, NotBondedPool, diff) + else both equal + end + keeper.bankKeeper -> store : transfer coins between modules + keeper.bankKeeper -> ctx.EventManager : emit TransferEvent(from, to, amount) + keeper.bankKeeper --> keeper + alt if there has been any updates to the validator set or the powers + keeper -> store : update LastTotalPower + end + end + keeper -> keeper : UnbondAllMatureValidators + group UnbondAllMatureValidators + keeper -> store : get ValidatorQueue up to current block height and time + keeper <-- store : `iterator` + loop for `validator` in `iterator` which are ready to unbond + keeper -> keeper : UnbondingToUnbonded(validator) + group UnbondingToUnbonded + keeper -> keeper : update validator object status + keeper -> store : set validator in storage + end + alt validator has zero shares (no active delegation) + keeper -> store : remove validator from key index + keeper -> store : remove validator from cons address index + keeper -> store : remove validator from power index + keeper -> keeper : AfterValidatorRemoved hook + end + end + loop for mature `delegation` in UnbondingQueue + keeper -> store : delete `delegation` from unbonding queue + keeper -> keeper : append `delegation` to `matureBonds` + end + loop for `delegation` in `matureBonds` + keeper -> keeper : CompleteUnbonding(delegation) + 'TODO what happens in CompleteUnbonding? + keeper -> ctx.EventManager : EventTypeCompleteUnbonding(amount, validator, delegator) + end + + loop for mature `redelegation` in RedelegationQueue + keeper -> store : delete `redelegation` from redelegation queue + keeper -> keeper : append `redelegation` to `matureRedelegations` + end + loop for `redelegation` in `matureRedelegations` + keeper -> keeper : CompleteRedelegation(redelegation) + 'TODO what happens in CompleteRedelegation? + keeper -> ctx.EventManager : EventTypeCompleteRedelegation(amount, delegator, src_validator, dst_validator) + end + + end + +end + +@enduml From 25ca4c39ae96e8c69d157929088a0f693df2e161 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:34:02 +0100 Subject: [PATCH 33/49] Add TODO --- x/staking/spec/endblock_sequence.puml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/staking/spec/endblock_sequence.puml b/x/staking/spec/endblock_sequence.puml index b0f4499ff859..93200f0d3162 100644 --- a/x/staking/spec/endblock_sequence.puml +++ b/x/staking/spec/endblock_sequence.puml @@ -42,6 +42,10 @@ group BlockValidatorUpdates note left : `last` now contains exactly the validators of the current block\nthat will not be validators in the next block. loop for validator in noLongerBonded keeper -> keeper : bondedToUnbonding(validator) + group bondedToUnbonding + keeper -> keeper + 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 + end keeper -> store : delete validator from power index keeper -> keeper : append validator and its new power (0) to `updates` end From ed646c0831c295811e5dc26efec9aa755ad7ce83 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:37:57 +0100 Subject: [PATCH 34/49] More visible TODOs --- x/staking/spec/endblock_sequence.puml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/staking/spec/endblock_sequence.puml b/x/staking/spec/endblock_sequence.puml index 93200f0d3162..3e54dccb7f2e 100644 --- a/x/staking/spec/endblock_sequence.puml +++ b/x/staking/spec/endblock_sequence.puml @@ -25,6 +25,7 @@ group BlockValidatorUpdates note left : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator group bondValidator keeper -> keeper + note right #DD0000 : TODO 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 end end @@ -44,7 +45,7 @@ group BlockValidatorUpdates keeper -> keeper : bondedToUnbonding(validator) group bondedToUnbonding keeper -> keeper - 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 + note right #DD0000 : TODO end keeper -> store : delete validator from power index keeper -> keeper : append validator and its new power (0) to `updates` From 6abbe9d98632a145b198c8cbb0610680e01c1996 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 26 Feb 2021 16:49:54 +0100 Subject: [PATCH 35/49] Remove numbering --- x/staking/spec/unbond_sequence.puml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/x/staking/spec/unbond_sequence.puml b/x/staking/spec/unbond_sequence.puml index 7852596491f9..aad8dcd47321 100644 --- a/x/staking/spec/unbond_sequence.puml +++ b/x/staking/spec/unbond_sequence.puml @@ -1,10 +1,6 @@ @startuml 'https://plantuml.com/sequence-diagram -autonumber - -title: Unbond message - msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount) keeper -> keeper : calculate number of shares the tokenAmount represents From 22fc57dfd02e0d9663ee51caca2063d4981d5f0f Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:25:14 +0100 Subject: [PATCH 36/49] Complete EndBlock --- x/staking/spec/endblock_sequence.puml | 102 +++++++++++++++++++------- 1 file changed, 77 insertions(+), 25 deletions(-) diff --git a/x/staking/spec/endblock_sequence.puml b/x/staking/spec/endblock_sequence.puml index 3e54dccb7f2e..8ff1b39b6b70 100644 --- a/x/staking/spec/endblock_sequence.puml +++ b/x/staking/spec/endblock_sequence.puml @@ -10,7 +10,7 @@ database store keeper -> keeper : BlockValidatorUpdates group BlockValidatorUpdates - note left : returns `updates`, a list of `abci.ValidatorUpdate`s + note left : returns `updates`, a list of `abci.ValidatorUpdate`s. keeper -> keeper : ApplyAndReturnValidatorSetUpdates group ApplyAndReturnValidatorSetUpdates keeper -> store : get the validators the set of validators for the beginning of the current block and their power. @@ -22,11 +22,15 @@ group BlockValidatorUpdates '`maxValidators` is just an upper bound. alt validator is unbonded or unbonding keeper -> keeper : bondValidator(validator) - note left : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator + note right : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator. group bondValidator - keeper -> keeper - note right #DD0000 : TODO - 'TODO describe bondValidator state updates x/staking/keeper/val_state_change.go:284 + keeper -> keeper : set validator's status to `Bonded` + keeper -> store : update the validator's state + keeper -> store : update the power index + note left : TODO Is this unncessary? [[https://github.com/cosmos/cosmos-sdk/issues/8764]]). + keeper -> store : delete validator from unbonding queue. + note left : Delete the whole time slice if this is the last waiting validator in the slice. + keeper -> keeper : AfterValidatorBonded(consAddress, operator) hook end end alt if validator power has changed @@ -41,11 +45,20 @@ group BlockValidatorUpdates ' last = all validators at the beginning of the block keeper -> keeper : noLongerBonded := `last` sorted by address note left : `last` now contains exactly the validators of the current block\nthat will not be validators in the next block. - loop for validator in noLongerBonded + loop for validator in noLongerBonded (bonded in this block, but not next) keeper -> keeper : bondedToUnbonding(validator) group bondedToUnbonding - keeper -> keeper - note right #DD0000 : TODO + keeper -> keeper : beginUnbondingValidator + group beginUnbondingValidator + keeper -> store : delete validator from power index + keeper -> keeper : change validator state to `Unbonding` + keeper -> keeper : set validator's unbonding time and unbonding height + keeper -> store : update the validator's state + keeper -> store : update the power index + keeper -> store : add validator to unbonding queue + note left : creates a new time slice if necessary + keeper -> keeper : AfterValidatorBeginUnbonding(consAddress, operator) hook + end end keeper -> store : delete validator from power index keeper -> keeper : append validator and its new power (0) to `updates` @@ -81,28 +94,67 @@ group BlockValidatorUpdates keeper -> keeper : AfterValidatorRemoved hook end end - loop for mature `delegation` in UnbondingQueue - keeper -> store : delete `delegation` from unbonding queue - keeper -> keeper : append `delegation` to `matureBonds` - end - loop for `delegation` in `matureBonds` - keeper -> keeper : CompleteUnbonding(delegation) - 'TODO what happens in CompleteUnbonding? - keeper -> ctx.EventManager : EventTypeCompleteUnbonding(amount, validator, delegator) + end + loop for mature `delegation` in UnbondingQueue + keeper -> store : delete `delegation` from unbonding queue + keeper -> keeper : append `delegation` to `matureBonds` + end + loop for `delegation` in `matureBonds` + keeper -> keeper : CompleteUnbonding(delegation) + group CompleteUnbonding + keeper -> store : GetUnbondingDelegation(delegatorAddress, validatorAddress) + keeper <-- store : `ubd` + alt unbonding delegation not found + keeper --> keeper : continue with next loop iteration + end + loop all delegations in `ubd` + 'Is this inefficient? Looping over all delegations again? + alt unbonding delegation is mature + keeper -> keeper : remove entry from `ubd` + alt unbonding delegation has a non-zero balance + keeper -> keeper.bankKeeper : UndelegateCoinsFromModuleToAccount(NotBondedPoolName, delegatorAddress, amount ) + end + end + end + alt the delegator has no remaining unbonding delegations to the validator + keeper -> store : remove unbonding delegation entry + else + keeper -> store : set unbonding delegation to updated `ubd` + end + keeper --> keeper : `amount` := return total unbonded balance end + keeper -> ctx.EventManager : EventTypeCompleteUnbonding(amount, validator, delegator) + end - loop for mature `redelegation` in RedelegationQueue - keeper -> store : delete `redelegation` from redelegation queue - keeper -> keeper : append `redelegation` to `matureRedelegations` - end - loop for `redelegation` in `matureRedelegations` - keeper -> keeper : CompleteRedelegation(redelegation) - 'TODO what happens in CompleteRedelegation? - keeper -> ctx.EventManager : EventTypeCompleteRedelegation(amount, delegator, src_validator, dst_validator) + loop for mature `redelegation` in RedelegationQueue + keeper -> store : delete `redelegation` from redelegation queue + keeper -> keeper : append `redelegation` to `matureRedelegations` + end + loop for `redelegation` in `matureRedelegations` + keeper -> keeper : CompleteRedelegation(redelegation) + group CompleteRedelegation + keeper -> store : GetRedelegation(delegatorAddress, validatorSrcAddress, validatorDstAddress) + keeper <-- store : `red` + alt redelegation not found + keeper --> keeper : continue with next loop iteration + end + loop all delegations in `red` + 'Is this inefficient? Looping over all delegations again? + alt redelegation is mature + keeper -> keeper : remove entry from `red` + end + end + alt the delegator- has no remaining redelegation to this pair of validators + keeper -> store : remove redelegation entry + else + keeper -> store : set redelegation to updated `red` + end + keeper --> keeper : `amount` := return total unbonded balance end - + keeper -> ctx.EventManager : EventTypeCompleteRedelegation(amount, delegator, src_validator, dst_validator) end end + @enduml From 5ca1ae838701a586bf355569d430b24e46c30cc0 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:25:56 +0100 Subject: [PATCH 37/49] Remove numbering --- docs/transaction_flow.puml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/transaction_flow.puml b/docs/transaction_flow.puml index 0d0ff82aabd3..d9b6cbcf626a 100644 --- a/docs/transaction_flow.puml +++ b/docs/transaction_flow.puml @@ -1,8 +1,6 @@ @startuml 'https://plantuml.com/sequence-diagram -autonumber - actor User User -> baseApp : Transaction Type baseApp -> router : Route(ctx, msgRoute) @@ -19,4 +17,4 @@ msgServer -> msgServer : maybe wrap results in more structure msgServer --> handler : result, error code baseApp <-- handler : results, error code -@enduml \ No newline at end of file +@enduml From 27720b03029d1865047bdb114ae50c8ea2a313b2 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:26:13 +0100 Subject: [PATCH 38/49] Remove TODOs and update title --- x/staking/spec/begin_redelegation_sequence.puml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/staking/spec/begin_redelegation_sequence.puml b/x/staking/spec/begin_redelegation_sequence.puml index 8c1dda30f295..315f063f464c 100644 --- a/x/staking/spec/begin_redelegation_sequence.puml +++ b/x/staking/spec/begin_redelegation_sequence.puml @@ -1,7 +1,7 @@ @startuml 'https://plantuml.com/sequence-diagram -title: Delegating (currently undelegated funds delegator) +title: Redelegation msgServer -> keeper : BeginRedelegation(delAddr, valSrcAddr, valDstAddr, sharesAmount) participant "keeper (staking)" as keeper @@ -23,14 +23,14 @@ end keeper -> keeper : Unbond(del, valSrc) returns returnAmount ... -note left : TODO: Describe unbond +note left : See unbonding diagram alt returnAmount is zero keeper -> msgServer : error end keeper -> keeper : Delegate(del, returnAmount, status := valSrc.status, valDst, subtractAccount := false) -note left : TODO: explore different statuses in Delegate +note left : See delegation diagram ... alt validator is unbonded From 7a1929b6eed5fbba907c9a12b6f7e17635ee56be Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:39:13 +0100 Subject: [PATCH 39/49] add title back --- x/staking/spec/unbond_sequence.puml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/staking/spec/unbond_sequence.puml b/x/staking/spec/unbond_sequence.puml index aad8dcd47321..17cbda07fd82 100644 --- a/x/staking/spec/unbond_sequence.puml +++ b/x/staking/spec/unbond_sequence.puml @@ -1,6 +1,8 @@ @startuml 'https://plantuml.com/sequence-diagram +title: Unbond + msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount) keeper -> keeper : calculate number of shares the tokenAmount represents From 6a0e944d983130627c2a53a4d91c0d81a97f0689 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Tue, 9 Mar 2021 18:05:46 +0100 Subject: [PATCH 40/49] remove endblock seq-diagram --- x/staking/spec/endblock_sequence.puml | 160 -------------------------- 1 file changed, 160 deletions(-) delete mode 100644 x/staking/spec/endblock_sequence.puml diff --git a/x/staking/spec/endblock_sequence.puml b/x/staking/spec/endblock_sequence.puml deleted file mode 100644 index 8ff1b39b6b70..000000000000 --- a/x/staking/spec/endblock_sequence.puml +++ /dev/null @@ -1,160 +0,0 @@ -@startuml -'https://plantuml.com/sequence-diagram - -title: EndBlock\nAt this point the - -participant keeper -participant keeper.bankKeeper -participant ctx.EventManager -database store - -keeper -> keeper : BlockValidatorUpdates -group BlockValidatorUpdates - note left : returns `updates`, a list of `abci.ValidatorUpdate`s. - keeper -> keeper : ApplyAndReturnValidatorSetUpdates - group ApplyAndReturnValidatorSetUpdates - keeper -> store : get the validators the set of validators for the beginning of the current block and their power. - keeper <-- store : `last` - keeper -> store : get the validators sorted by their current power (possibly updated in the block), highest to least. - keeper <-- store : `iterator` - loop for the first `maxValidators` validators in `iterator` - 'If there are less than `maxValidators`, then jut loop over all of them. - '`maxValidators` is just an upper bound. - alt validator is unbonded or unbonding - keeper -> keeper : bondValidator(validator) - note right : unbonded and unbonding treated as separate cases in the code,\nbut both just call bondValidator. - group bondValidator - keeper -> keeper : set validator's status to `Bonded` - keeper -> store : update the validator's state - keeper -> store : update the power index - note left : TODO Is this unncessary? [[https://github.com/cosmos/cosmos-sdk/issues/8764]]). - keeper -> store : delete validator from unbonding queue. - note left : Delete the whole time slice if this is the last waiting validator in the slice. - keeper -> keeper : AfterValidatorBonded(consAddress, operator) hook - end - end - alt if validator power has changed - keeper -> store : update validator's power in power index (add it if not already present) - keeper -> keeper : append validator and its new power to `updates` - end - keeper -> keeper : delete validator from `last` map - end - 'After loop: totalPower = amount of power of the new validator set - ' amtFromNotBondedToBonded = number of previously not bonded tokens now bonded - ' amtFromBondedToNotBonded = 0 - ' last = all validators at the beginning of the block - keeper -> keeper : noLongerBonded := `last` sorted by address - note left : `last` now contains exactly the validators of the current block\nthat will not be validators in the next block. - loop for validator in noLongerBonded (bonded in this block, but not next) - keeper -> keeper : bondedToUnbonding(validator) - group bondedToUnbonding - keeper -> keeper : beginUnbondingValidator - group beginUnbondingValidator - keeper -> store : delete validator from power index - keeper -> keeper : change validator state to `Unbonding` - keeper -> keeper : set validator's unbonding time and unbonding height - keeper -> store : update the validator's state - keeper -> store : update the power index - keeper -> store : add validator to unbonding queue - note left : creates a new time slice if necessary - keeper -> keeper : AfterValidatorBeginUnbonding(consAddress, operator) hook - end - end - keeper -> store : delete validator from power index - keeper -> keeper : append validator and its new power (0) to `updates` - end - 'After loop: amtFromBondedToNotBonded = number of previously bonded tokens now not bonded - alt newly bonded tokens > newly not bonded tokens - keeper -> keeper.bankKeeper : sendCoinsFromModuleToModule(NotBondedPool, BondedPool, diff) - else newly bonded tokens < newly not bonded tokens - keeper -> keeper.bankKeeper : sendCoinsFromModuleToModule(BondedPool, NotBondedPool, diff) - else both equal - end - keeper.bankKeeper -> store : transfer coins between modules - keeper.bankKeeper -> ctx.EventManager : emit TransferEvent(from, to, amount) - keeper.bankKeeper --> keeper - alt if there has been any updates to the validator set or the powers - keeper -> store : update LastTotalPower - end - end - keeper -> keeper : UnbondAllMatureValidators - group UnbondAllMatureValidators - keeper -> store : get ValidatorQueue up to current block height and time - keeper <-- store : `iterator` - loop for `validator` in `iterator` which are ready to unbond - keeper -> keeper : UnbondingToUnbonded(validator) - group UnbondingToUnbonded - keeper -> keeper : update validator object status - keeper -> store : set validator in storage - end - alt validator has zero shares (no active delegation) - keeper -> store : remove validator from key index - keeper -> store : remove validator from cons address index - keeper -> store : remove validator from power index - keeper -> keeper : AfterValidatorRemoved hook - end - end - end - loop for mature `delegation` in UnbondingQueue - keeper -> store : delete `delegation` from unbonding queue - keeper -> keeper : append `delegation` to `matureBonds` - end - loop for `delegation` in `matureBonds` - keeper -> keeper : CompleteUnbonding(delegation) - group CompleteUnbonding - keeper -> store : GetUnbondingDelegation(delegatorAddress, validatorAddress) - keeper <-- store : `ubd` - alt unbonding delegation not found - keeper --> keeper : continue with next loop iteration - end - loop all delegations in `ubd` - 'Is this inefficient? Looping over all delegations again? - alt unbonding delegation is mature - keeper -> keeper : remove entry from `ubd` - alt unbonding delegation has a non-zero balance - keeper -> keeper.bankKeeper : UndelegateCoinsFromModuleToAccount(NotBondedPoolName, delegatorAddress, amount ) - end - end - end - alt the delegator has no remaining unbonding delegations to the validator - keeper -> store : remove unbonding delegation entry - else - keeper -> store : set unbonding delegation to updated `ubd` - end - keeper --> keeper : `amount` := return total unbonded balance - end - keeper -> ctx.EventManager : EventTypeCompleteUnbonding(amount, validator, delegator) - end - - loop for mature `redelegation` in RedelegationQueue - keeper -> store : delete `redelegation` from redelegation queue - keeper -> keeper : append `redelegation` to `matureRedelegations` - end - loop for `redelegation` in `matureRedelegations` - keeper -> keeper : CompleteRedelegation(redelegation) - group CompleteRedelegation - keeper -> store : GetRedelegation(delegatorAddress, validatorSrcAddress, validatorDstAddress) - keeper <-- store : `red` - alt redelegation not found - keeper --> keeper : continue with next loop iteration - end - loop all delegations in `red` - 'Is this inefficient? Looping over all delegations again? - alt redelegation is mature - keeper -> keeper : remove entry from `red` - end - end - alt the delegator- has no remaining redelegation to this pair of validators - keeper -> store : remove redelegation entry - else - keeper -> store : set redelegation to updated `red` - end - keeper --> keeper : `amount` := return total unbonded balance - end - keeper -> ctx.EventManager : EventTypeCompleteRedelegation(amount, delegator, src_validator, dst_validator) - end - -end - - -@enduml From 7b4ab55f256a8648d01bdf208f6ab7a3d9fa04d1 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 10 Mar 2021 14:53:45 +0100 Subject: [PATCH 41/49] Make power index update conditional on not being jailed --- x/staking/spec/delegation_sequence.puml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x/staking/spec/delegation_sequence.puml b/x/staking/spec/delegation_sequence.puml index 9a99f0b7e5a4..ad0286476b8d 100644 --- a/x/staking/spec/delegation_sequence.puml +++ b/x/staking/spec/delegation_sequence.puml @@ -75,8 +75,10 @@ keeper <-- validator : validator, addedShares keeper -> store : update validator state keeper -> keeper: calculate new validator's power note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18) -keeper -> store : update validator's power in power index -note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. +alt validator is not jailed + keeper -> store : update validator's power in power index + note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low. +end keeper -> keeper : AfterDelegationModified hook note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info. From 4dda1702417469801d091527eccd9a8fde648754 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Wed, 10 Mar 2021 14:53:52 +0100 Subject: [PATCH 42/49] update title --- x/staking/spec/unbond_sequence.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/staking/spec/unbond_sequence.puml b/x/staking/spec/unbond_sequence.puml index 17cbda07fd82..bfe385b42b69 100644 --- a/x/staking/spec/unbond_sequence.puml +++ b/x/staking/spec/unbond_sequence.puml @@ -1,7 +1,7 @@ @startuml 'https://plantuml.com/sequence-diagram -title: Unbond +title: Undelegate msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount) From b02943d3d7bee0201ac4736899e55e68f608e013 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 16:20:23 +0200 Subject: [PATCH 43/49] Move files to /docs --- {x/staking/spec => docs/uml}/begin_redelegation_sequence.puml | 0 {x/staking/spec => docs/uml}/delegation_sequence.puml | 0 {x/staking/spec => docs/uml}/keeper_dependencies.puml | 0 docs/{ => uml}/transaction_flow.puml | 0 {x/staking/spec => docs/uml}/unbond_sequence.puml | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {x/staking/spec => docs/uml}/begin_redelegation_sequence.puml (100%) rename {x/staking/spec => docs/uml}/delegation_sequence.puml (100%) rename {x/staking/spec => docs/uml}/keeper_dependencies.puml (100%) rename docs/{ => uml}/transaction_flow.puml (100%) rename {x/staking/spec => docs/uml}/unbond_sequence.puml (100%) diff --git a/x/staking/spec/begin_redelegation_sequence.puml b/docs/uml/begin_redelegation_sequence.puml similarity index 100% rename from x/staking/spec/begin_redelegation_sequence.puml rename to docs/uml/begin_redelegation_sequence.puml diff --git a/x/staking/spec/delegation_sequence.puml b/docs/uml/delegation_sequence.puml similarity index 100% rename from x/staking/spec/delegation_sequence.puml rename to docs/uml/delegation_sequence.puml diff --git a/x/staking/spec/keeper_dependencies.puml b/docs/uml/keeper_dependencies.puml similarity index 100% rename from x/staking/spec/keeper_dependencies.puml rename to docs/uml/keeper_dependencies.puml diff --git a/docs/transaction_flow.puml b/docs/uml/transaction_flow.puml similarity index 100% rename from docs/transaction_flow.puml rename to docs/uml/transaction_flow.puml diff --git a/x/staking/spec/unbond_sequence.puml b/docs/uml/unbond_sequence.puml similarity index 100% rename from x/staking/spec/unbond_sequence.puml rename to docs/uml/unbond_sequence.puml From 8fb7a40df1bc7dfb3ab5c7b3ee71a58f5e8612a9 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:29:12 +0200 Subject: [PATCH 44/49] Install PlantUML and compile images to png and txt --- Dockerfile | 2 +- docs/pre.sh | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index af8b4c1febce..973fcf2a7b43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ FROM golang:alpine AS build-env # Install minimum necessary dependencies, -ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 +ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 plantuml RUN apk add --no-cache $PACKAGES # Set working directory for the build diff --git a/docs/pre.sh b/docs/pre.sh index 47e4329fbf5c..b018bc731afe 100755 --- a/docs/pre.sh +++ b/docs/pre.sh @@ -9,4 +9,7 @@ for D in ../x/*; do fi done -cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md \ No newline at end of file +cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md + +plantuml -tutxt uml/*.puml +plantuml -tsvg uml/*.puml From 1a0d992b3fb8017d641ac2291ee1a9211b8ed3ae Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:30:54 +0200 Subject: [PATCH 45/49] Use transaction flow in documentation --- docs/building-modules/msg-services.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/building-modules/msg-services.md b/docs/building-modules/msg-services.md index 868d74b4a21d..ce7713c01b12 100644 --- a/docs/building-modules/msg-services.md +++ b/docs/building-modules/msg-services.md @@ -54,6 +54,10 @@ This method takes care of marshaling the `res` parameter to protobuf and attachi +++ https://github.com/cosmos/cosmos-sdk/blob/d55c1a26657a0af937fa2273b38dcfa1bb3cff9f/proto/cosmos/base/abci/v1beta1/abci.proto#L81-L95 +This diagram shows a typical structure of an `Msg` Service, and how the message propagates through the module. + +![](../uml/transaction_flow.svg) + ## Legacy Amino `Msg`s ### `handler` type From 656a278b22f089386f967c384715dc9139e09fd9 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:33:49 +0200 Subject: [PATCH 46/49] Use staking UML in staking docs --- x/staking/spec/03_messages.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index d0f059ecf6b6..a3dbca9a9e2a 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -75,6 +75,8 @@ The delegator receives newly minted shares at the current exchange rate. The exchange rate is the number of existing shares in the validator divided by the number of currently delegated tokens. +![](docs/uml/delegation_sequence.svg) + ## Msg/Undelegate The `Msg/Undelegate` service message allows delegators to undelegate their tokens from @@ -107,6 +109,8 @@ When this service message is processed the following actions occur: - if there are no more `Shares` in the delegation, then the delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. +![](docs/uml/unbond_sequence.svg) + ## Msg/BeginRedelegate The redelegation command allows delegators to instantly switch validators. Once @@ -141,3 +145,5 @@ When this service message is processed the following actions occur: - Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. - if there are no more `Shares` in the source delegation, then the source delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. + +![](docs/uml/begin_redelegation_sequence.svg) From 47e330df32f8d9bfe797e7ad46bc0fa158d8c199 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:48:11 +0200 Subject: [PATCH 47/49] Clarify uml with inline doc --- docs/uml/transaction_flow.puml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/uml/transaction_flow.puml b/docs/uml/transaction_flow.puml index d9b6cbcf626a..bf01f04f68b7 100644 --- a/docs/uml/transaction_flow.puml +++ b/docs/uml/transaction_flow.puml @@ -1,3 +1,5 @@ +What happens after a transaction is unmarshalled and is processed by the SDK? + @startuml 'https://plantuml.com/sequence-diagram From aa6950b29a0861a4ca412e3dca7147c59618e007 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 22:17:19 +0200 Subject: [PATCH 48/49] Add keeper deps diagram to docs --- docs/core/ocap.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/core/ocap.md b/docs/core/ocap.md index db8d0b7e5c86..2264d46bff67 100644 --- a/docs/core/ocap.md +++ b/docs/core/ocap.md @@ -70,6 +70,10 @@ gaia app. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.41.4/simapp/app.go#L249-L273 +The following diagram shows the current dependencies between keepers. + +![](../uml/keeper_dependencies.svg) + ## Next {hide} Learn about the [`runTx` middleware](./runtx_middleware.md) {hide} From 6c5650ce3e0c460676d341aa50dd389cd6ae7c80 Mon Sep 17 00:00:00 2001 From: hjort <8545447+hjorthjort@users.noreply.github.com> Date: Mon, 5 Apr 2021 22:17:51 +0200 Subject: [PATCH 49/49] Only produce SVG images --- docs/pre.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/pre.sh b/docs/pre.sh index b018bc731afe..e5a0f9fe131b 100755 --- a/docs/pre.sh +++ b/docs/pre.sh @@ -11,5 +11,4 @@ done cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md -plantuml -tutxt uml/*.puml plantuml -tsvg uml/*.puml