Staking part2 (#1755)
* Revert "remove old design code"
This reverts commit 58448f6b23
.
* fix revert conflicts
* change blspubkey type as 48 bytes for easily serialization
* WIP
* remove redelegate txType
* update delegator and validatorWrapper data structure
* fix golang test
* move txType into message creation
* remove validatorMap on statedb; move validatprMap update logic up to higher level of codes and from onchain to offchain.
pull/1764/head
parent
0a4e4d6339
commit
942456f564
@ -0,0 +1,18 @@ |
||||
package staking |
||||
|
||||
import ( |
||||
"github.com/ethereum/go-ethereum/crypto" |
||||
) |
||||
|
||||
const ( |
||||
isValidatorKeyStr = "Harmony/IsValidator/v0" |
||||
isValidatorStr = "Harmony/IsAValidator/v0" |
||||
isNotValidatorStr = "Harmony/IsNotAValidator/v0" |
||||
) |
||||
|
||||
// keys used to retrieve staking related informatio
|
||||
var ( |
||||
IsValidatorKey = crypto.Keccak256Hash([]byte(isValidatorKeyStr)) |
||||
IsValidator = crypto.Keccak256Hash([]byte(isValidatorStr)) |
||||
IsNotValidator = crypto.Keccak256Hash([]byte(isNotValidatorStr)) |
||||
) |
@ -1,249 +1,72 @@ |
||||
package types |
||||
|
||||
import ( |
||||
"fmt" |
||||
"errors" |
||||
"math/big" |
||||
"strings" |
||||
|
||||
"github.com/ethereum/go-ethereum/rlp" |
||||
"github.com/harmony-one/harmony/internal/common" |
||||
) |
||||
|
||||
// DVPair is struct that just has a delegator-validator pair with no other data.
|
||||
// It is intended to be used as a marshalable pointer. For example, a DVPair can be used to construct the
|
||||
// key to getting an UnbondingDelegation from state.
|
||||
type DVPair struct { |
||||
DelegatorAddress common.Address |
||||
ValidatorAddress common.Address |
||||
} |
||||
|
||||
// DVVTriplet is struct that just has a delegator-validator-validator triplet with no other data.
|
||||
// It is intended to be used as a marshalable pointer. For example, a DVVTriplet can be used to construct the
|
||||
// key to getting a Redelegation from state.
|
||||
type DVVTriplet struct { |
||||
DelegatorAddress common.Address |
||||
ValidatorSrcAddress common.Address |
||||
ValidatorDstAddress common.Address |
||||
} |
||||
var ( |
||||
errInsufficientBalance = errors.New("Insufficient balance to undelegate") |
||||
errInvalidAmount = errors.New("Invalid amount, must be positive") |
||||
) |
||||
|
||||
// Delegation represents the bond with tokens held by an account. It is
|
||||
// owned by one delegator, and is associated with the voting power of one
|
||||
// validator.
|
||||
type Delegation struct { |
||||
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` |
||||
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"` |
||||
Amount *big.Int `json:"amount" yaml:"amount"` |
||||
Entries []*UndelegationEntry `json:"entries" yaml:"entries"` |
||||
} |
||||
|
||||
// UndelegationEntry represents one undelegation entry
|
||||
type UndelegationEntry struct { |
||||
Amount *big.Int |
||||
Epoch *big.Int |
||||
} |
||||
|
||||
// NewDelegation creates a new delegation object
|
||||
func NewDelegation(delegatorAddr common.Address, validatorAddr common.Address, |
||||
func NewDelegation(delegatorAddr common.Address, |
||||
amount *big.Int) Delegation { |
||||
|
||||
return Delegation{ |
||||
DelegatorAddress: delegatorAddr, |
||||
ValidatorAddress: validatorAddr, |
||||
Amount: amount, |
||||
} |
||||
} |
||||
|
||||
// MarshalDelegation return the delegation
|
||||
func MarshalDelegation(delegation Delegation) ([]byte, error) { |
||||
return rlp.EncodeToBytes(delegation) |
||||
} |
||||
|
||||
// UnmarshalDelegation return the delegation
|
||||
func UnmarshalDelegation(by []byte) (*Delegation, error) { |
||||
decoded := &Delegation{} |
||||
err := rlp.DecodeBytes(by, decoded) |
||||
return decoded, err |
||||
} |
||||
|
||||
// GetDelegatorAddr returns DelegatorAddr
|
||||
func (d Delegation) GetDelegatorAddr() common.Address { return d.DelegatorAddress } |
||||
|
||||
// GetValidatorAddr returns ValidatorAddr
|
||||
func (d Delegation) GetValidatorAddr() common.Address { return d.ValidatorAddress } |
||||
|
||||
// GetAmount returns amount of a delegation
|
||||
func (d Delegation) GetAmount() *big.Int { return d.Amount } |
||||
|
||||
// String returns a human readable string representation of a Delegation.
|
||||
func (d Delegation) String() string { |
||||
return fmt.Sprintf(` |
||||
Delegation: |
||||
Delegator: %s |
||||
Validator: %s |
||||
Amount: %s |
||||
`, d.DelegatorAddress, d.ValidatorAddress, d.Amount) |
||||
} |
||||
|
||||
// Delegations is a collection of delegations
|
||||
type Delegations []Delegation |
||||
|
||||
// String returns the string representation of a list of delegations
|
||||
func (d Delegations) String() (out string) { |
||||
for _, del := range d { |
||||
out += del.String() + "\n" |
||||
} |
||||
return strings.TrimSpace(out) |
||||
} |
||||
|
||||
// UnbondingDelegation stores all of a single delegator's unbonding bonds
|
||||
// for a single validator in an time-ordered list
|
||||
type UnbondingDelegation struct { |
||||
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` // delegator
|
||||
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"` // validator unbonding from operator addr
|
||||
Entries []UnbondingDelegationEntry `json:"entries" yaml:"entries"` // unbonding delegation entries
|
||||
// AddEntry - append entry to the undelegation
|
||||
func (d *Delegation) AddEntry(epoch *big.Int, amt *big.Int) error { |
||||
if d.Amount.Cmp(amt) < 0 { |
||||
return errInsufficientBalance |
||||
} |
||||
|
||||
// UnbondingDelegationEntry - entry to an UnbondingDelegation
|
||||
type UnbondingDelegationEntry struct { |
||||
ExitEpoch *big.Int `json:"exit_epoch" yaml:"exit_epoch"` // epoch which the unbonding begins
|
||||
Amount *big.Int `json:"amount" yaml:"amount"` // atoms to receive at completion
|
||||
if amt.Sign() <= 0 { |
||||
return errInvalidAmount |
||||
} |
||||
d.Amount.Sub(d.Amount, amt) |
||||
|
||||
// NewUnbondingDelegation - create a new unbonding delegation object
|
||||
func NewUnbondingDelegation(delegatorAddr common.Address, |
||||
validatorAddr common.Address, epoch *big.Int, amt *big.Int) UnbondingDelegation { |
||||
|
||||
entry := NewUnbondingDelegationEntry(epoch, amt) |
||||
return UnbondingDelegation{ |
||||
DelegatorAddress: delegatorAddr, |
||||
ValidatorAddress: validatorAddr, |
||||
Entries: []UnbondingDelegationEntry{entry}, |
||||
for _, entry := range d.Entries { |
||||
if entry.Epoch.Cmp(epoch) == 0 { |
||||
entry.Amount.Add(entry.Amount, amt) |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
// NewUnbondingDelegationEntry - create a new unbonding delegation object
|
||||
func NewUnbondingDelegationEntry(epoch *big.Int, amt *big.Int) UnbondingDelegationEntry { |
||||
return UnbondingDelegationEntry{ |
||||
ExitEpoch: epoch, |
||||
Amount: amt, |
||||
} |
||||
item := UndelegationEntry{amt, epoch} |
||||
d.Entries = append(d.Entries, &item) |
||||
return nil |
||||
} |
||||
|
||||
// AddEntry - append entry to the unbonding delegation
|
||||
// if there exists same ExitEpoch entry, merge the amount
|
||||
// TODO: check the total amount not exceed the staking amount call this function
|
||||
func (d *UnbondingDelegation) AddEntry(epoch *big.Int, amt *big.Int) { |
||||
entry := NewUnbondingDelegationEntry(epoch, amt) |
||||
for i := range d.Entries { |
||||
if d.Entries[i].ExitEpoch == entry.ExitEpoch { |
||||
d.Entries[i].Amount.Add(d.Entries[i].Amount, entry.Amount) |
||||
return |
||||
} |
||||
} |
||||
// same exit epoch entry not found
|
||||
d.Entries = append(d.Entries, entry) |
||||
return |
||||
} |
||||
|
||||
// String returns a human readable string representation of an UnbondingDelegation.
|
||||
func (d UnbondingDelegation) String() string { |
||||
out := fmt.Sprintf(`Unbonding Delegations between: |
||||
Delegator: %s |
||||
Validator: %s |
||||
Entries:`, d.DelegatorAddress, d.ValidatorAddress) |
||||
// DeleteEntry - delete an entry from the undelegation
|
||||
// Opimize it
|
||||
func (d *Delegation) DeleteEntry(epoch *big.Int) { |
||||
entries := []*UndelegationEntry{} |
||||
for i, entry := range d.Entries { |
||||
out += fmt.Sprintf(` Unbonding Delegation %d: |
||||
ExitEpoch: %v |
||||
Amount: %s`, i, entry.ExitEpoch, entry.Amount) |
||||
if entry.Epoch.Cmp(epoch) == 0 { |
||||
entries = append(d.Entries[:i], d.Entries[i+1:]...) |
||||
} |
||||
return out |
||||
} |
||||
|
||||
// UnbondingDelegations is a collection of UnbondingDelegation
|
||||
type UnbondingDelegations []UnbondingDelegation |
||||
|
||||
func (ubds UnbondingDelegations) String() (out string) { |
||||
for _, u := range ubds { |
||||
out += u.String() + "\n" |
||||
} |
||||
return strings.TrimSpace(out) |
||||
} |
||||
|
||||
// Redelegation contains the list of a particular delegator's
|
||||
// redelegating bonds from a particular source validator to a
|
||||
// particular destination validator
|
||||
type Redelegation struct { |
||||
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` // delegator
|
||||
ValidatorSrcAddress common.Address `json:"validator_src_address" yaml:"validator_src_address"` // validator redelegation source operator addr
|
||||
ValidatorDstAddress common.Address `json:"validator_dst_address" yaml:"validator_dst_address"` // validator redelegation destination operator addr
|
||||
Entries []RedelegationEntry `json:"entries" yaml:"entries"` // redelegation entries
|
||||
} |
||||
|
||||
// RedelegationEntry - entry to a Redelegation
|
||||
type RedelegationEntry struct { |
||||
Epoch *big.Int `json:"epoch" yaml:"epoch"` // epoch at which the redelegation took place
|
||||
Amount *big.Int `json:"amount" yaml:"amount"` // amount of destination-validator tokens created by redelegation
|
||||
} |
||||
|
||||
// NewRedelegation - create a new redelegation object
|
||||
func NewRedelegation(delegatorAddr common.Address, validatorSrcAddr, |
||||
validatorDstAddr common.Address, epoch *big.Int, amt *big.Int) Redelegation { |
||||
entry := NewRedelegationEntry(epoch, amt) |
||||
return Redelegation{ |
||||
DelegatorAddress: delegatorAddr, |
||||
ValidatorSrcAddress: validatorSrcAddr, |
||||
ValidatorDstAddress: validatorDstAddr, |
||||
Entries: []RedelegationEntry{entry}, |
||||
} |
||||
} |
||||
|
||||
// NewRedelegationEntry - create a new redelegation object
|
||||
func NewRedelegationEntry(epoch *big.Int, amt *big.Int) RedelegationEntry { |
||||
return RedelegationEntry{ |
||||
Epoch: epoch, |
||||
Amount: amt, |
||||
} |
||||
} |
||||
|
||||
// AddEntry - append entry to the unbonding delegation
|
||||
// Merge if has same epoch field
|
||||
func (d *Redelegation) AddEntry(epoch *big.Int, amt *big.Int) { |
||||
entry := NewRedelegationEntry(epoch, amt) |
||||
|
||||
for i := range d.Entries { |
||||
if d.Entries[i].Epoch == entry.Epoch { |
||||
d.Entries[i].Amount.Add(d.Entries[i].Amount, entry.Amount) |
||||
return |
||||
} |
||||
} |
||||
// same epoch entry not found
|
||||
d.Entries = append(d.Entries, entry) |
||||
return |
||||
} |
||||
|
||||
// String returns a human readable string representation of a Redelegation.
|
||||
func (d Redelegation) String() string { |
||||
out := fmt.Sprintf(` |
||||
Redelegations between: |
||||
Delegator: %s |
||||
Source Validator: %s |
||||
Destination Validator: %s |
||||
Entries: |
||||
`, |
||||
d.DelegatorAddress, d.ValidatorSrcAddress, d.ValidatorDstAddress, |
||||
) |
||||
|
||||
for i, entry := range d.Entries { |
||||
out += fmt.Sprintf(` Redelegation Entry #%d: |
||||
Epoch: %v |
||||
Amount: %v |
||||
`, |
||||
i, entry.Epoch, entry.Amount, |
||||
) |
||||
} |
||||
|
||||
return strings.TrimRight(out, "\n") |
||||
} |
||||
|
||||
// Redelegations are a collection of Redelegation
|
||||
type Redelegations []Redelegation |
||||
|
||||
func (d Redelegations) String() (out string) { |
||||
for _, red := range d { |
||||
out += red.String() + "\n" |
||||
if entries != nil { |
||||
d.Entries = entries |
||||
} |
||||
return strings.TrimSpace(out) |
||||
} |
||||
|
Loading…
Reference in new issue