be more consistent in use of "period", "state", etc wrt. proposals
- specify maximum cosigners requirement in spec. - remove silly qualified names in Proposal impl.
This commit is contained in:
parent
9dd5bed05e
commit
2865f2f093
4 changed files with 39 additions and 34 deletions
|
|
@ -107,6 +107,7 @@ proposal =
|
|||
Value.assetClass govSymbol ""
|
||||
, stakeSTAssetClass =
|
||||
Value.assetClass stakeSymbol ""
|
||||
, maximumCosigners = 6
|
||||
}
|
||||
|
||||
proposalPolicySymbol :: CurrencySymbol
|
||||
|
|
|
|||
|
|
@ -84,8 +84,10 @@ newtype ResultTag = ResultTag {getResultTag :: Integer}
|
|||
deriving stock (Eq, Show, Ord)
|
||||
deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData)
|
||||
|
||||
{- | The "status" of the proposal. This is only useful for state transitions,
|
||||
as opposed to time-based "phases".
|
||||
{- | The "status" of the proposal. This is only useful for state transitions that
|
||||
need to happen as a result of a transaction as opposed to time-based "periods".
|
||||
|
||||
See the note on wording & the state machine in the tech-design.
|
||||
|
||||
If the proposal is 'VotingReady', for instance, that doesn't necessarily
|
||||
mean that voting is possible, as this also requires the timing to be right.
|
||||
|
|
@ -220,7 +222,7 @@ data ProposalRedeemer
|
|||
-- === @* -> 'Finished'@:
|
||||
--
|
||||
-- If the proposal has run out of time for the current 'ProposalStatus', it will always be possible
|
||||
-- to transition into 'Finished' state, because it has expired (and failed).
|
||||
-- to transition into 'Finished' status, because it has expired (and failed).
|
||||
AdvanceProposal
|
||||
deriving stock (Eq, Show, GHC.Generic)
|
||||
|
||||
|
|
@ -236,6 +238,8 @@ PlutusTx.makeIsDataIndexed
|
|||
data Proposal = Proposal
|
||||
{ governorSTAssetClass :: AssetClass
|
||||
, stakeSTAssetClass :: AssetClass
|
||||
, maximumCosigners :: Integer
|
||||
-- ^ Arbitrary limit for maximum amount of cosigners on a proposal.
|
||||
}
|
||||
deriving stock (Show, Eq)
|
||||
|
||||
|
|
@ -395,11 +399,11 @@ deriving via (DerivePConstantViaData ProposalRedeemer PProposalRedeemer) instanc
|
|||
--------------------------------------------------------------------------------
|
||||
|
||||
{- | Check for various invariants a proposal must uphold.
|
||||
This can be used to check both upopn creation and
|
||||
This can be used to check both upon creation and
|
||||
upon any following state transitions in the proposal.
|
||||
-}
|
||||
proposalDatumValid :: Term s (Agora.Proposal.PProposalDatum :--> PBool)
|
||||
proposalDatumValid =
|
||||
proposalDatumValid :: Proposal -> Term s (Agora.Proposal.PProposalDatum :--> PBool)
|
||||
proposalDatumValid proposal =
|
||||
phoistAcyclic $
|
||||
plam $ \datum' -> P.do
|
||||
datum <- pletFields @'["effects", "cosigners"] $ datum'
|
||||
|
|
@ -420,5 +424,5 @@ proposalDatumValid =
|
|||
(#&&)
|
||||
[ ptraceIfFalse "Proposal has at least one ResultTag has no effects" atLeastOneNegativeResult
|
||||
, ptraceIfFalse "Proposal has at least one cosigner" $ pnotNull # pfromData datum.cosigners
|
||||
, ptraceIfFalse "Proposal has at most five cosigners" $ plength # (pfromData datum.cosigners) #< 6
|
||||
, ptraceIfFalse "Proposal has at most five cosigners" $ plength # (pfromData datum.cosigners) #<= pconstant proposal.maximumCosigners
|
||||
]
|
||||
|
|
|
|||
|
|
@ -48,20 +48,20 @@ import Plutus.V1.Ledger.Value (AssetClass (AssetClass))
|
|||
NOTE: The governor needs to check that the datum is correct
|
||||
and sent to the right address.
|
||||
-}
|
||||
proposalPolicy :: Agora.Proposal.Proposal -> ClosedTerm Plutarch.Api.V1.PMintingPolicy
|
||||
proposalPolicy :: Proposal -> ClosedTerm PMintingPolicy
|
||||
proposalPolicy proposal =
|
||||
plam $ \_redeemer ctx' -> P.do
|
||||
Plutarch.Api.V1.PScriptContext ctx' <- pmatch ctx'
|
||||
PScriptContext ctx' <- pmatch ctx'
|
||||
ctx <- pletFields @'["txInfo", "purpose"] ctx'
|
||||
Plutarch.Api.V1.PTxInfo txInfo' <- pmatch $ pfromData ctx.txInfo
|
||||
PTxInfo txInfo' <- pmatch $ pfromData ctx.txInfo
|
||||
txInfo <- pletFields @'["inputs", "mint"] txInfo'
|
||||
Plutarch.Api.V1.PMinting _ownSymbol <- pmatch $ pfromData ctx.purpose
|
||||
PMinting _ownSymbol <- pmatch $ pfromData ctx.purpose
|
||||
|
||||
let inputs = txInfo.inputs
|
||||
mintedValue = pfromData txInfo.mint
|
||||
AssetClass (govCs, govTn) = proposal.governorSTAssetClass
|
||||
|
||||
Plutarch.Api.V1.PMinting ownSymbol' <- pmatch $ pfromData ctx.purpose
|
||||
PMinting ownSymbol' <- pmatch $ pfromData ctx.purpose
|
||||
let mintedProposalST = passetClassValueOf # mintedValue # (passetClass # (pfield @"_0" # ownSymbol') # pconstant "")
|
||||
|
||||
passert "Governance state-thread token must move" $
|
||||
|
|
@ -75,15 +75,15 @@ proposalPolicy proposal =
|
|||
popaque (pconstant ())
|
||||
|
||||
-- | Validator for Proposals.
|
||||
proposalValidator :: Agora.Proposal.Proposal -> ClosedTerm Plutarch.Api.V1.PValidator
|
||||
proposalValidator :: Proposal -> ClosedTerm PValidator
|
||||
proposalValidator proposal =
|
||||
plam $ \datum redeemer ctx' -> P.do
|
||||
Plutarch.Api.V1.PScriptContext ctx' <- pmatch ctx'
|
||||
PScriptContext ctx' <- pmatch ctx'
|
||||
ctx <- pletFields @'["txInfo", "purpose"] ctx'
|
||||
txInfo <- plet $ pfromData ctx.txInfo
|
||||
Plutarch.Api.V1.PTxInfo txInfo' <- pmatch txInfo
|
||||
PTxInfo txInfo' <- pmatch txInfo
|
||||
txInfoF <- pletFields @'["inputs", "mint", "datums", "signatories"] txInfo'
|
||||
Plutarch.Api.V1.PSpending ((pfield @"_0" #) -> txOutRef) <- pmatch $ pfromData ctx.purpose
|
||||
PSpending ((pfield @"_0" #) -> txOutRef) <- pmatch $ pfromData ctx.purpose
|
||||
|
||||
PJust txOut <- pmatch $ findTxOutByTxOutRef # txOutRef # txInfoF.inputs
|
||||
txOutF <- pletFields @'["address", "value"] $ txOut
|
||||
|
|
@ -114,13 +114,13 @@ proposalValidator proposal =
|
|||
signedBy <- plet $ ptxSignedBy # txInfoF.signatories
|
||||
|
||||
pmatch proposalRedeemer $ \case
|
||||
Agora.Proposal.PVote _r -> P.do
|
||||
PVote _r -> P.do
|
||||
passert "ST at inputs must be 1" $
|
||||
spentST #== 1
|
||||
|
||||
popaque (pconstant ())
|
||||
--------------------------------------------------------------------------
|
||||
Agora.Proposal.PCosign r -> P.do
|
||||
PCosign r -> P.do
|
||||
newSigs <- plet $ pfield @"newCosigners" # r
|
||||
|
||||
passert "ST at inputs must be 1" $
|
||||
|
|
@ -143,14 +143,14 @@ proposalValidator proposal =
|
|||
# newSigs
|
||||
|
||||
passert "Signatures are correctly added to cosignature list" $
|
||||
anyOutput @Agora.Proposal.PProposalDatum # ctx.txInfo
|
||||
anyOutput @PProposalDatum # ctx.txInfo
|
||||
#$ plam
|
||||
$ \newValue address newProposalDatum -> P.do
|
||||
let correctDatum =
|
||||
pdata newProposalDatum
|
||||
#== pdata
|
||||
( mkRecordConstr
|
||||
Agora.Proposal.PProposalDatum
|
||||
PProposalDatum
|
||||
( #proposalId .= proposalF.proposalId
|
||||
.& #effects .= proposalF.effects
|
||||
.& #status .= proposalF.status
|
||||
|
|
@ -170,13 +170,13 @@ proposalValidator proposal =
|
|||
|
||||
popaque (pconstant ())
|
||||
--------------------------------------------------------------------------
|
||||
Agora.Proposal.PUnlock _r -> P.do
|
||||
PUnlock _r -> P.do
|
||||
passert "ST at inputs must be 1" $
|
||||
spentST #== 1
|
||||
|
||||
popaque (pconstant ())
|
||||
--------------------------------------------------------------------------
|
||||
Agora.Proposal.PAdvanceProposal _r -> P.do
|
||||
PAdvanceProposal _r -> P.do
|
||||
passert "ST at inputs must be 1" $
|
||||
spentST #== 1
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ Initiating a proposal requires the proposer to have more than a certain amount o
|
|||
|
||||
### Voting stages
|
||||
|
||||
The life-cycle of a proposal is neatly represented by a state machine, with the 'draft' phase being the initial state, and 'executed' and 'failed' being the terminating states.
|
||||
The life-cycle of a proposal is neatly represented by a state machine, with the 'draft' state being the initial state, and 'executed' and 'failed' being the terminating states.
|
||||
|
||||
**Please note that this state-machine representation is purely conceptual and should not be expected to reflect technical implementation.** This is because some state transitions in the state machine representation don't need to happen in the actual implementation as a transaction. A key example is going from the "lock" phase to the "execution" phase. The only thing that needs to happen is that time goes by. So under the hood, they are represented the same in the Proposal's datum.
|
||||
**Please note that this state-machine representation is purely conceptual and should not be expected to reflect technical implementation.** This is because some state transitions in the state machine representation don't need to happen in the actual implementation as a transaction. A key example is going from the "lock" phase to the "execution" phase. The only thing that needs to happen is that time goes by. So under the hood, they are represented the same in the Proposal's datum. Furthermore, in order to make our wording consistent, we use _"period"_ to mean a time-based, and _"status"_ to mean what is encoded in the datum. "State", then, refers to the more vague notion of what the state machine would look like.
|
||||
|
||||
> Emily 2022-04-27: This is quite confusing still, I feel. @Jack, could you try to reword this and make it more clear?
|
||||
|
||||
|
|
@ -54,21 +54,21 @@ Consider the following 'stages' of a proposal:
|
|||
- `L`: the length of the locking period.
|
||||
- `E`: the length of the execution period.
|
||||
|
||||
| Action | Valid POSIXTimeRange | Valid _stored_ state(s) |
|
||||
|-------------------------------------|-------------------------------------|-------------------------|
|
||||
| Witness | \[S, ∞) | \* |
|
||||
| Cosign | \[S, S + D) | Draft |
|
||||
| AdvanceProposal | \[S, S + D) | Draft |
|
||||
| Vote | \[S + D, S + D + V) | Voting |
|
||||
| Unlock | \[S + D, ∞) | \* |
|
||||
| CountVotes | \[S + D + V, S + D + V + L) | Voting |
|
||||
| ExecuteProposal (if quorum reached) | \[S + D + V + L, S + D + V + L + E) | Voting |
|
||||
| Action | Valid POSIXTimeRange | Valid _stored_ status(es) |
|
||||
|-------------------------------------|-------------------------------------|---------------------------|
|
||||
| Witness | \[S, ∞) | \* |
|
||||
| Cosign | \[S, S + D) | Draft |
|
||||
| AdvanceProposal | \[S, S + D) | Draft |
|
||||
| Vote | \[S + D, S + D + V) | Voting |
|
||||
| Unlock | \[S + D, ∞) | \* |
|
||||
| CountVotes | \[S + D + V, S + D + V + L) | Voting |
|
||||
| ExecuteProposal (if quorum reached) | \[S + D + V + L, S + D + V + L + E) | Voting |
|
||||
|
||||
> Jack 2022-02-02: I will consider revising this table further at a later time.
|
||||
|
||||
#### Draft phase
|
||||
|
||||
During the draft phase, a new UTXO at the proposal script has been created. At this stage, only votes in favor of co-signing the draft are counted. For the proposal to transition to the voting phase, a threshold of GT will have to be staked backing the proposal. This threshold will be determined on a per-system basis and could itself be a 'governable' parameter. It's important to note that cosignatures are not locking votes. Cosignatures are more like a delegated approval to a proposal. The sum of all cosignatures must tally to the threshold, and all cosigner stake datums must fit into a single transaction to witness their size.
|
||||
During the draft phase, a new UTXO at the proposal script has been created. At this stage, only votes in favor of co-signing the draft are counted. For the proposal to transition to the voting phase, a threshold of GT will have to be staked backing the proposal. This threshold will be determined on a per-system basis and could itself be a 'governable' parameter. It's important to note that cosignatures are not locking votes. Cosignatures are more like a delegated approval to a proposal. The sum of all cosignatures must tally to the threshold, and all cosigner stake datums must fit into a single transaction to witness their size. A limit on the maximum amount of cosigners is placed in order to prevent a situation where the stake datums no longer fit in the transaction. The number doesn't matter and may be expressed in a parametrized way.
|
||||
|
||||
#### Voting phase
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue