commit
d1dc6cc445
|
@ -13,13 +13,13 @@ has to be created and the previous one rendered inactive.
|
|||
```go
|
||||
type DepositProcedure struct {
|
||||
MinDeposit sdk.Coins // Minimum deposit for a proposal to enter voting period.
|
||||
MaxDepositPeriod time.Time // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
MaxDepositPeriod int64 // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
type VotingProcedure struct {
|
||||
VotingPeriod time.Time // Length of the voting period. Initial value: 2 weeks
|
||||
VotingPeriod int64 // Length of the voting period. Initial value: 2 weeks
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -28,7 +28,7 @@ type TallyingProcedure struct {
|
|||
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||
GovernancePenalty sdk.Dec // Penalty if validator does not vote
|
||||
GracePeriod time.Time // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
||||
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -97,10 +97,10 @@ type Proposal struct {
|
|||
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
||||
TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit
|
||||
Deposits []Deposit // List of deposits on the proposal
|
||||
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
|
||||
SubmitBlock int64 // Height of the block where TxGovSubmitProposal was included
|
||||
Submitter sdk.Address // Address of the submitter
|
||||
|
||||
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
|
||||
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||
CurrentStatus ProposalStatus // Current status of the proposal
|
||||
|
||||
YesVotes sdk.Dec
|
||||
|
@ -137,7 +137,7 @@ For pseudocode purposes, here are the two function we will use to read or write
|
|||
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
|
||||
`ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest
|
||||
element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if
|
||||
`CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is,
|
||||
`CurrentBlock == VotingStartBlock + activeProcedure.VotingPeriod`. If it is,
|
||||
then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted
|
||||
and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded.
|
||||
After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated.
|
||||
|
@ -159,7 +159,7 @@ And the pseudocode for the `ProposalProcessingQueue`:
|
|||
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
|
||||
votingProcedure = load(GlobalParams, 'VotingProcedure')
|
||||
|
||||
if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
|
||||
if (CurrentBlock == proposal.VotingStartBlock + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
|
||||
|
||||
// End of voting period, tally
|
||||
|
||||
|
@ -194,7 +194,7 @@ And the pseudocode for the `ProposalProcessingQueue`:
|
|||
|
||||
// Slash validators that did not vote, or update tally if they voted
|
||||
for each validator in validators
|
||||
if (validator.bondTime < CurrentTime - tallyingProcedure.GracePeriod)
|
||||
if (validator.bondHeight < CurrentBlock - tallyingProcedure.GracePeriod)
|
||||
// only slash if validator entered validator set before grace period
|
||||
if (!tmpValMap(validator).HasVoted)
|
||||
slash validator by tallyingProcedure.GovernancePenalty
|
||||
|
|
|
@ -2,7 +2,6 @@ package gov
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -29,18 +28,12 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
|
|||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
||||
newHeader := ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
EndBlocker(ctx, keeper)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
||||
newHeader = ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(250)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
EndBlocker(ctx, keeper)
|
||||
|
@ -66,10 +59,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
|||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
||||
newHeader := ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
EndBlocker(ctx, keeper)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
@ -78,20 +68,14 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
|
|||
res = govHandler(ctx, newProposalMsg2)
|
||||
require.True(t, res.IsOK())
|
||||
|
||||
newHeader = ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(205)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
EndBlocker(ctx, keeper)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
||||
newHeader = ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(215)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.True(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
EndBlocker(ctx, keeper)
|
||||
|
@ -121,10 +105,7 @@ func TestTickPassedDepositPeriod(t *testing.T) {
|
|||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
||||
newHeader := ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
EndBlocker(ctx, keeper)
|
||||
require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx))
|
||||
require.False(t, shouldPopInactiveProposalQueue(ctx, keeper))
|
||||
|
@ -165,20 +146,14 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
|||
var proposalID int64
|
||||
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
|
||||
|
||||
newHeader := ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)})
|
||||
res = govHandler(ctx, newDepositMsg)
|
||||
require.True(t, res.IsOK())
|
||||
|
||||
EndBlocker(ctx, keeper)
|
||||
|
||||
newHeader = ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(215)
|
||||
require.True(t, shouldPopActiveProposalQueue(ctx, keeper))
|
||||
depositsIterator := keeper.GetDeposits(ctx, proposalID)
|
||||
require.True(t, depositsIterator.Valid())
|
||||
|
@ -222,10 +197,7 @@ func TestSlashing(t *testing.T) {
|
|||
var proposalID int64
|
||||
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
|
||||
|
||||
newHeader := ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
|
||||
|
||||
newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes)
|
||||
|
@ -234,10 +206,7 @@ func TestSlashing(t *testing.T) {
|
|||
|
||||
EndBlocker(ctx, keeper)
|
||||
|
||||
newHeader = ctx.BlockHeader()
|
||||
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
|
||||
ctx = ctx.WithBlockHeader(newHeader)
|
||||
|
||||
ctx = ctx.WithBlockHeight(215)
|
||||
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
|
||||
|
||||
EndBlocker(ctx, keeper)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package gov
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -29,10 +27,10 @@ func DefaultGenesisState() GenesisState {
|
|||
StartingProposalID: 1,
|
||||
DepositProcedure: DepositProcedure{
|
||||
MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)},
|
||||
MaxDepositPeriod: time.Duration(172800) * time.Second,
|
||||
MaxDepositPeriod: 200,
|
||||
},
|
||||
VotingProcedure: VotingProcedure{
|
||||
VotingPeriod: time.Duration(172800) * time.Second,
|
||||
VotingPeriod: 200,
|
||||
},
|
||||
TallyingProcedure: TallyingProcedure{
|
||||
Threshold: sdk.NewDecWithPrec(5, 1),
|
||||
|
|
|
@ -122,9 +122,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
|||
for shouldPopActiveProposalQueue(ctx, keeper) {
|
||||
activeProposal := keeper.ActiveProposalQueuePop(ctx)
|
||||
|
||||
proposalStartTime := activeProposal.GetVotingStartTime()
|
||||
proposalStartBlock := activeProposal.GetVotingStartBlock()
|
||||
votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod
|
||||
if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) {
|
||||
if ctx.BlockHeight() < proposalStartBlock+votingPeriod {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
|||
return false
|
||||
} else if peekProposal.GetStatus() != StatusDepositPeriod {
|
||||
return true
|
||||
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) {
|
||||
} else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -184,7 +184,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
|||
|
||||
if peekProposal == nil {
|
||||
return false
|
||||
} else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) {
|
||||
} else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -73,7 +73,8 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description
|
|||
Status: StatusDepositPeriod,
|
||||
TallyResult: EmptyTallyResult(),
|
||||
TotalDeposit: sdk.Coins{},
|
||||
SubmitTime: ctx.BlockHeader().Time,
|
||||
SubmitBlock: ctx.BlockHeight(),
|
||||
VotingStartBlock: -1, // TODO: Make Time
|
||||
}
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
keeper.InactiveProposalQueuePush(ctx, proposal)
|
||||
|
@ -199,7 +200,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e
|
|||
}
|
||||
|
||||
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
||||
proposal.SetVotingStartTime(ctx.BlockHeader().Time)
|
||||
proposal.SetVotingStartBlock(ctx.BlockHeight())
|
||||
proposal.SetStatus(StatusVotingPeriod)
|
||||
keeper.SetProposal(ctx, proposal)
|
||||
keeper.ActiveProposalQueuePush(ctx, proposal)
|
||||
|
|
|
@ -2,7 +2,6 @@ package gov
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -46,12 +45,12 @@ func TestActivateVotingPeriod(t *testing.T) {
|
|||
|
||||
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
|
||||
|
||||
require.True(t, proposal.GetVotingStartTime().Equal(time.Time{}))
|
||||
require.Equal(t, int64(-1), proposal.GetVotingStartBlock())
|
||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
||||
|
||||
keeper.activateVotingPeriod(ctx, proposal)
|
||||
|
||||
require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||
require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight())
|
||||
require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
|
||||
}
|
||||
|
||||
|
@ -78,7 +77,7 @@ func TestDeposits(t *testing.T) {
|
|||
// Check no deposits at beginning
|
||||
deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1])
|
||||
require.False(t, found)
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{}))
|
||||
require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1))
|
||||
require.Nil(t, keeper.ActiveProposalQueuePeek(ctx))
|
||||
|
||||
// Check first deposit
|
||||
|
@ -115,7 +114,7 @@ func TestDeposits(t *testing.T) {
|
|||
require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1]))
|
||||
|
||||
// Check that proposal moved to voting period
|
||||
require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time))
|
||||
require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock())
|
||||
require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx))
|
||||
require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID())
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package gov
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Procedure around Deposits for governance
|
||||
type DepositProcedure struct {
|
||||
MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period.
|
||||
MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
}
|
||||
|
||||
// Procedure around Tallying votes in governance
|
||||
|
@ -21,5 +19,5 @@ type TallyingProcedure struct {
|
|||
|
||||
// Procedure around Voting in governance
|
||||
type VotingProcedure struct {
|
||||
VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period.
|
||||
VotingPeriod int64 `json:"voting_period"` // Length of the voting period.
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package gov
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
|
@ -31,14 +30,14 @@ type Proposal interface {
|
|||
GetTallyResult() TallyResult
|
||||
SetTallyResult(TallyResult)
|
||||
|
||||
GetSubmitTime() time.Time
|
||||
SetSubmitTime(time.Time)
|
||||
GetSubmitBlock() int64
|
||||
SetSubmitBlock(int64)
|
||||
|
||||
GetTotalDeposit() sdk.Coins
|
||||
SetTotalDeposit(sdk.Coins)
|
||||
|
||||
GetVotingStartTime() time.Time
|
||||
SetVotingStartTime(time.Time)
|
||||
GetVotingStartBlock() int64
|
||||
SetVotingStartBlock(int64)
|
||||
}
|
||||
|
||||
// checks if two proposals are equal
|
||||
|
@ -49,9 +48,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
|
|||
proposalA.GetProposalType() == proposalB.GetProposalType() &&
|
||||
proposalA.GetStatus() == proposalB.GetStatus() &&
|
||||
proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) &&
|
||||
proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) &&
|
||||
proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() &&
|
||||
proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) &&
|
||||
proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) {
|
||||
proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -68,10 +67,10 @@ type TextProposal struct {
|
|||
Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected}
|
||||
TallyResult TallyResult `json:"tally_result"` // Result of Tallys
|
||||
|
||||
SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included
|
||||
SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included
|
||||
TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit
|
||||
|
||||
VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||
VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||
}
|
||||
|
||||
// Implements Proposal Interface
|
||||
|
@ -90,13 +89,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S
|
|||
func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status }
|
||||
func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult }
|
||||
func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult }
|
||||
func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime }
|
||||
func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime }
|
||||
func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock }
|
||||
func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock }
|
||||
func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit }
|
||||
func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit }
|
||||
func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime }
|
||||
func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) {
|
||||
tp.VotingStartTime = votingStartTime
|
||||
func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock }
|
||||
func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) {
|
||||
tp.VotingStartBlock = votingStartBlock
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue