Skip to content

Commit

Permalink
[PVM, Dependencies] AddProposalTx, AddVoteTx, FinishProposalsTx
Browse files Browse the repository at this point in the history
  • Loading branch information
evlekht committed Aug 16, 2023
1 parent fadf074 commit ab94af2
Show file tree
Hide file tree
Showing 13 changed files with 981 additions and 17 deletions.
49 changes: 47 additions & 2 deletions api/v2.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2022, Chain4Travel AG. All rights reserved.
// Copyright (C) 2022-2023, Chain4Travel AG. All rights reserved.
//
// This file is a derived work, based on ava-labs code whose
// original notices appear below.
Expand Down Expand Up @@ -153,7 +153,9 @@ func AddV2Routes(ctx *Context, router *web.Router, path string, indexBytes []byt
Get("/cacheassetaggregates", (*V2Context).CacheAssetAggregates).
Get("/cacheaggregates/:id", (*V2Context).CacheAggregates).
Get("/multisigalias/:owners", (*V2Context).GetMultisigAlias).
Post("/rewards", (*V2Context).GetRewardPost)
Post("/rewards", (*V2Context).GetRewardPost).
Get("/proposals", (*V2Context).ListDACProposals).
Get("/proposals/:id/votes", (*V2Context).GetDACProposalVotes)
}

// AVAX
Expand Down Expand Up @@ -1145,3 +1147,46 @@ func (c *V2Context) CacheAggregates(w web.ResponseWriter, r *web.Request) {

WriteJSON(w, b)
}

func (c *V2Context) ListDACProposals(w web.ResponseWriter, r *web.Request) {
collectors := utils.NewCollectors(
utils.NewCounterObserveMillisCollect(MetricMillis),
utils.NewCounterIncCollect(MetricCount),
)
defer func() {
_ = collectors.Collect()
}()

params := &params.ListDACProposalsParams{}
if err := params.ForValues(c.version, r.URL.Query()); err != nil {
c.WriteErr(w, 400, err)
return
}

c.WriteCacheable(w, caching.Cacheable{
TTL: 5 * time.Second,
Key: c.cacheKeyForParams("list_dac_proposals", params),
CacheableFn: func(ctx context.Context) (interface{}, error) {
return c.avaxReader.ListDACProposals(ctx, params)
},
})
}

func (c *V2Context) GetDACProposalVotes(w web.ResponseWriter, r *web.Request) {
collectors := utils.NewCollectors(
utils.NewCounterObserveMillisCollect(MetricMillis),
utils.NewCounterIncCollect(MetricCount),
)
defer func() {
_ = collectors.Collect()
}()

proposalID := r.PathParams["id"]
c.WriteCacheable(w, caching.Cacheable{
TTL: 5 * time.Second,
Key: c.cacheKeyForID("get_dac_proposal_votes", proposalID),
CacheableFn: func(ctx context.Context) (interface{}, error) {
return c.avaxReader.GetDACProposalVotes(ctx, proposalID)
},
})
}
195 changes: 194 additions & 1 deletion db/dbmodel.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2022, Chain4Travel AG. All rights reserved.
// Copyright (C) 2022-2023, Chain4Travel AG. All rights reserved.
//
// This file is a derived work, based on ava-labs code whose
// original notices appear below.
Expand All @@ -21,6 +21,7 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/chain4travel/magellan/models"
"github.com/chain4travel/magellan/services/indexes/params"
"github.com/chain4travel/magellan/utils"
"github.com/gocraft/dbr/v2"
)
Expand Down Expand Up @@ -56,6 +57,8 @@ const (
TableMultisigAliases = "multisig_aliases"
TableReward = "reward"
TableRewardOwner = "reward_owner"
TableDACProposals = "dac_proposals"
TableDACVotes = "dac_votes"
)

type Persist interface {
Expand Down Expand Up @@ -440,6 +443,45 @@ type Persist interface {
dbr.SessionRunner,
*Reward,
) error

InsertDACProposal(
ctx context.Context,
session dbr.SessionRunner,
proposal *DACProposal,
) error

UpdateDACProposalsStatus(
ctx context.Context,
session dbr.SessionRunner,
proposalIDs []string,
proposalStatus models.ProposalStatus,
) error

FinishDACProposal(
ctx context.Context,
session dbr.SessionRunner,
proposalID string,
proposalStatus models.ProposalStatus,
outcome []byte,
) error

QueryDACProposals(
ctx context.Context,
session dbr.SessionRunner,
params *params.ListDACProposalsParams,
) ([]DACProposal, error)

InsertDACVote(
ctx context.Context,
session dbr.SessionRunner,
vote *DACVote,
) error

QueryDACProposalVotes(
ctx context.Context,
session dbr.SessionRunner,
proposalID string,
) ([]DACVote, error)
}

type persist struct{}
Expand Down Expand Up @@ -2390,3 +2432,154 @@ func (p *persist) DeactivateReward(ctx context.Context, session dbr.SessionRunne

return p.InsertReward(ctx, session, v)
}

type DACProposal struct {
ID string `db:"id"` // proposal id, also addProposalTx id
ProposerAddr string `db:"proposer_addr"` // address which authorized proposal
StartTime time.Time `db:"start_time"` // time when proposal will become votable
EndTime time.Time `db:"end_time"` // time when proposal will become non-votable and will be executed if its successful
Type models.ProposalType `db:"type"` // proposal type
Options []byte `db:"options"` // proposal votable options
Memo []byte `db:"memo"` // addProposalTx memo
Outcome []byte `db:"outcome"` // outcome of successful proposal, usually is one or multiple options indexes
Status models.ProposalStatus `db:"status"` // current status of proposal
}

func (p *persist) InsertDACProposal(ctx context.Context, session dbr.SessionRunner, proposal *DACProposal) error {
_, err := session.
InsertInto(TableDACProposals).
Pair("id", proposal.ID).
Pair("proposer_addr", proposal.ProposerAddr).
Pair("start_time", proposal.StartTime).
Pair("end_time", proposal.EndTime).
Pair("type", proposal.Type).
Pair("options", proposal.Options).
Pair("status", proposal.Status).
ExecContext(ctx)
if err != nil {
return EventErr(TableDACProposals, false, err)
}
return nil
}

func (p *persist) UpdateDACProposalsStatus(
ctx context.Context,
session dbr.SessionRunner,
proposalIDs []string,
proposalStatus models.ProposalStatus,
) error {
_, err := session.
Update(TableDACProposals).
Set("status", proposalStatus).
Where("id IN ?", proposalIDs).
ExecContext(ctx)
if err != nil {
return EventErr(TableDACProposals, false, err)
}
return nil
}

func (p *persist) FinishDACProposal(
ctx context.Context,
session dbr.SessionRunner,
proposalID string,
proposalStatus models.ProposalStatus,
outcome []byte,
) error {
_, err := session.
Update(TableDACProposals).
Set("status", proposalStatus).
Set("outcome", outcome).
Where("id = ?", proposalID).
ExecContext(ctx)
if err != nil {
return EventErr(TableDACProposals, false, err)
}
return nil
}

func (p *persist) QueryDACProposals(
ctx context.Context,
session dbr.SessionRunner,
params *params.ListDACProposalsParams,
) ([]DACProposal, error) {
v := &[]DACProposal{}
query := session.Select(
"P.id",
"P.proposer_addr",
"P.start_time",
"P.end_time",
"P.type",
"P.options",
"T.memo",
"P.outcome",
"P.status",
).From(dbr.I(TableDACProposals).As("P")).
Join(dbr.I(TableTransactions).As("T"), "T.id=P.id")

if params.Offset > 0 {
query.Offset(uint64(params.Offset))
}
if params.Limit > 0 {
query.Limit(uint64(params.Limit))
}
if params.ListParams.StartTimeProvided {
query.Where("P.start_time <= ?", params.StartTime)
}
if params.EndTimeProvided {
query.Where("P.end_time >= ?", params.EndTime)
}
if params.ProposalType != nil {
query.Where("P.type = ?", params.ProposalType)
}
if params.ProposalStatus != nil {
if *params.ProposalStatus == models.ProposalStatusCompleted {
query.Where("P.status = ? OR P.status = ?", models.ProposalStatusSuccess, models.ProposalStatusFailed)
} else {
query.Where("P.status = ?", params.ProposalStatus)
}
}

_, err := query.LoadContext(ctx, v)
return *v, err
}

type DACVote struct {
VoteTxID string `db:"id"` // addVoteTx id
VoterAddr string `db:"voter_addr"` // address which authorized this vote
VotedAt time.Time `db:"voted_at"` // timestamp when this vote happened
ProposalID string `db:"proposal_id"` // id of proposal that was voted on
VotedOptions []byte `db:"voted_options"` // proposal options that was voted by this vote, usually one or multiple option indexes
}

func (p *persist) InsertDACVote(ctx context.Context, session dbr.SessionRunner, vote *DACVote) error {
_, err := session.
InsertInto(TableDACVotes).
Pair("id", vote.VoteTxID).
Pair("voter_addr", vote.VoterAddr).
Pair("voted_at", vote.VotedAt).
Pair("proposal_id", vote.ProposalID).
Pair("voted_options", vote.VotedOptions).
ExecContext(ctx)
if err != nil {
return EventErr(TableDACVotes, false, err)
}
return nil
}

func (p *persist) QueryDACProposalVotes(
ctx context.Context,
session dbr.SessionRunner,
proposalID string,
) ([]DACVote, error) {
v := &[]DACVote{}
_, err := session.Select(
"id",
"voter_addr",
"voted_at",
"voted_options",
).From(TableDACVotes).
Where("proposal_id = ?", proposalID).
LoadContext(ctx, v)
return *v, err
}
Loading

0 comments on commit ab94af2

Please sign in to comment.