Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync formal spec and implementation in EPOCH rule #1687

Merged
merged 1 commit into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Data.Aeson (FromJSON (..), ToJSON (..), (.!=), (.:), (.:?), (.=))
import qualified Data.Aeson as Aeson
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe (catMaybes)
import Data.Proxy (Proxy (..))
import Data.Scientific (Scientific)
import Data.Text (Text)
Expand Down Expand Up @@ -210,6 +211,7 @@ initialFundsPseudoTxIn addr =
data ValidationErr
= EpochNotLongEnough EpochSize Word64 Rational EpochSize
| MaxKESEvolutionsUnsupported Word64 Word
| QuorumTooSmall Word64 Word64 Word64
deriving (Eq, Show)

describeValidationErr :: ValidationErr -> Text
Expand All @@ -234,6 +236,17 @@ describeValidationErr (MaxKESEvolutionsUnsupported reqKES supportedKES) =
" but the algorithm supports a maximum of ",
Text.pack (show supportedKES)
]
describeValidationErr (QuorumTooSmall q maxTooSmal nodes) =
mconcat
[ "You have specified an 'updateQuorum' which is",
" too small compared to the number of genesis nodes.",
" You requested ",
Text.pack (show q),
", but given ",
Text.pack (show nodes),
" genesis nodes 'updateQuorum' must be greater than ",
Text.pack (show maxTooSmal)
]

-- | Do some basic sanity checking on the Shelley genesis file.
validateGenesis ::
Expand All @@ -246,16 +259,19 @@ validateGenesis
{ sgEpochLength,
sgActiveSlotsCoeff,
sgMaxKESEvolutions,
sgSecurityParam
sgSecurityParam,
sgUpdateQuorum,
sgGenDelegs
} =
case [ x
| Just cel <- [checkEpochLength],
Just cke <- [checkKesEvolutions],
x <- [cel, cke]
] of
case catMaybes errors of
[] -> Right ()
xs -> Left xs
where
errors =
[ checkEpochLength,
checkKesEvolutions,
checkQuorumSize
]
checkEpochLength =
let minLength =
EpochSize . ceiling $
Expand All @@ -278,3 +294,9 @@ validateGenesis
MaxKESEvolutionsUnsupported
sgMaxKESEvolutions
(totalPeriodsKES (Proxy @(KES c)))
checkQuorumSize =
let numGenesisNodes = fromIntegral $ length sgGenDelegs
maxTooSmal = numGenesisNodes `div` 2
in if numGenesisNodes == 0 || sgUpdateQuorum > maxTooSmal
then Nothing
else Just $ QuorumTooSmall sgUpdateQuorum maxTooSmal numGenesisNodes
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ data EpochState crypto = EpochState
esLState :: !(LedgerState crypto),
esPrevPp :: !PParams,
esPp :: !PParams,
esNonMyopic :: !(NonMyopic crypto)
esNonMyopic :: !(NonMyopic crypto) -- TODO document this in the formal spec, see github #1319
}
deriving (Show, Eq, Generic)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,29 @@ initialEpoch =
emptyPParams
emptyNonMyopic

votedValuePParams ::
votedValue ::
ProposedPPUpdates crypto ->
PParams ->
Int ->
Maybe PParams
votedValuePParams (ProposedPPUpdates ppup) pps quorumN =
votedValue (ProposedPPUpdates pup) pps quorumN =
let incrTally vote tally = 1 + Map.findWithDefault 0 vote tally
votes =
Map.foldr
(\vote tally -> Map.insert vote (incrTally vote tally) tally)
(Map.empty :: Map PParamsUpdate Int)
ppup
pup
consensus = Map.filter (>= quorumN) votes
in case length consensus of
-- NOTE that `quorumN` is a global constant, and that we require
-- it to be strictly greater than half the number of genesis nodes.
-- The keys in the `pup` correspond to the genesis nodes,
-- and therefore either:
-- 1) `consensus` is empty, or
-- 2) `consensus` has exactly one element.
1 -> (Just . updatePParams pps . fst . head . Map.toList) consensus
-- NOTE that `updatePParams` corresponds to the union override right
-- operation in the formal spec.
_ -> Nothing

epochTransition ::
Expand Down Expand Up @@ -129,8 +137,8 @@ epochTransition = do

coreNodeQuorum <- liftSTS $ asks quorum

let ppup = proposals . _ppups $ utxoSt
let ppNew = votedValuePParams ppup pp (fromIntegral coreNodeQuorum)
let pup = proposals . _ppups $ utxoSt'
let ppNew = votedValue pup pp (fromIntegral coreNodeQuorum)
NewppState utxoSt'' acnt'' pp' <-
trans @(NEWPP crypto) $
TRC (NewppEnv dstate' pstate'', NewppState utxoSt' acnt' pp, ppNew)
Expand Down
17 changes: 9 additions & 8 deletions shelley/chain-and-ledger/formal-spec/epoch.tex
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ \subsection{Complete Epoch Boundary Transition}
The transition uses a helper function $\fun{votedValue}$ which returns
the consensus value of update proposals in the event that consensus is met.
\textbf{Note that} $\fun{votedValue}$
\textbf{is only well-defined if } $\Quorum$
\textbf{is only well-defined if } $\var{quorum}$
\textbf{is greater than half the number of core nodes, i.e.}
$\Quorum > |\var{genDelegs}|/2$ \textbf{.}

Expand Down Expand Up @@ -805,12 +805,13 @@ \subsection{Complete Epoch Boundary Transition}
%
\emph{Helper Functions}
\begin{align*}
& \fun{votedValue} \in (\KeyHashGen\mapsto\PParamsUpdate) \to \PParamsUpdate^?\\
& \fun{votedValue}~\var{vs} =
\begin{cases}
p & \exists p\in\range{vs}~(|vs\restrictrange p|\geq \Quorum) \\
\Nothing & \text{otherwise} \\
\end{cases}
& \fun{votedValue} \in (\KeyHashGen\mapsto\PParamsUpdate) \to \PParams \to \N \to \PParamsUpdate^?\\
& \fun{votedValue}~\var{pup}~\var{pps}~\var{quorum} =
\begin{cases}
\var{pps}\unionoverrideRight\var{p}
& \exists! p\in\range{vs}~(|vs\restrictrange p|\geq \var{quorum}) \\
\Nothing & \text{otherwise} \\
\end{cases}
\end{align*}
%
\caption{Epoch transition-system types}
Expand Down Expand Up @@ -881,7 +882,7 @@ \subsection{Complete Epoch Boundary Transition}
\\~\\~\\
\var{(\wcard,~\wcard,~\wcard,~(\var{pup},\wcard))}\leteq\var{utxoSt'}\\
\var{pp_{new}}\leteq\var{pp}\unionoverrideRight
\fun{votedValue}~\var{pup}\\
\fun{votedValue}~\var{pup}~\var{pps}~\Quorum\\
{
\begin{array}{r}
\var{dstate'}\\
Expand Down