Skip to content

Commit

Permalink
Byron update proposal and vote api integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Jimbo4350 committed Dec 11, 2020
1 parent f8dfcc6 commit 7a1a798
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 163 deletions.
1 change: 1 addition & 0 deletions cardano-api/cardano-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ library
Cardano.Api.SerialiseJSON
Cardano.Api.SerialiseRaw
Cardano.Api.SerialiseTextEnvelope
Cardano.Api.SpecialByron
Cardano.Api.StakePoolMetadata
Cardano.Api.Tx
Cardano.Api.TxBody
Expand Down
17 changes: 17 additions & 0 deletions cardano-api/src/Cardano/Api/Byron.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,28 @@ module Cardano.Api.Byron
-- * Address
NetworkMagic(..),

-- * Update Proposal
ByronUpdateProposal(..),
createByronUpdateProposal,
serialiseByronUpdateProposal,
deserialiseByronUpdateProposal,
updateProposalToGenTx,
ParametersToUpdate(..),
createProtocolParametersUpdate,

-- * Vote
ByronVote(..),
createByronVote,
serialiseByronVote,
deserialiseByronVote,
voteToGenTx,

-- ** Conversions
toByronNetworkMagic,
toByronProtocolMagicId,
toByronRequiresNetworkMagic,
) where

import Cardano.Api
import Cardano.Api.SpecialByron
import Cardano.Api.Typed
4 changes: 2 additions & 2 deletions cardano-api/src/Cardano/Api/KeysByron.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ import qualified Cardano.Crypto.DSIGN.Class as Crypto
import qualified Cardano.Crypto.Seed as Crypto
import qualified Cardano.Crypto.Wallet as Crypto.HD

import qualified Cardano.Chain.Common as Byron
import qualified Cardano.Crypto.Hashing as Byron
import qualified Cardano.Crypto.Signing as Byron
import qualified Cardano.Chain.Common as Byron

import Cardano.Api.HasTypeProxy
import Cardano.Api.Hash
import Cardano.Api.HasTypeProxy
import Cardano.Api.Key
import Cardano.Api.KeysShelley
import Cardano.Api.SerialiseBech32
Expand Down
174 changes: 174 additions & 0 deletions cardano-api/src/Cardano/Api/SpecialByron.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
-- | Special Byron values that we can submit to a node to propose an update proposal
-- or to vote on an update proposal. These are not transactions.
--
module Cardano.Api.SpecialByron
( ByronUpdateProposal(..),
serialiseByronUpdateProposal,
deserialiseByronUpdateProposal,
updateProposalToGenTx,
ParametersToUpdate(..),
createProtocolParametersUpdate,
ByronVote(..),
createByronUpdateProposal,
createByronVote,
serialiseByronVote,
deserialiseByronVote,
voteToGenTx,
) where

import Cardano.Prelude (void)
import Prelude

import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as LB
import qualified Data.Map.Strict as M
import Data.Word
import Numeric.Natural


import Cardano.Api.Key
import Cardano.Api.KeysByron
import Cardano.Api.NetworkId (NetworkId, toByronProtocolMagicId)

import qualified Cardano.Binary as CBOR
import Cardano.Chain.Common (LovelacePortion, TxFeePolicy)
import Cardano.Chain.Slotting
import Cardano.Chain.Update
import Cardano.Crypto (SafeSigner, noPassSafeSigner)
import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock)
import qualified Ouroboros.Consensus.Byron.Ledger.Mempool as Mempool

-- | Byron era update proposal

newtype ByronUpdateProposal a = ByronUpdateProposal { unByronUpdateProposal :: AProposal a}

createByronUpdateProposal
:: NetworkId
-> ProtocolVersion
-> SoftwareVersion
-> SystemTag
-> InstallerHash
-> SigningKey ByronKey
-> [ParametersToUpdate]
-> ByronUpdateProposal ()
createByronUpdateProposal nId pVer sVer sysTag insHash (ByronSigningKey sKey) paramsToUpdate =
ByronUpdateProposal $ signProposal (toByronProtocolMagicId nId) proposalBody noPassSigningKey
where
proposalBody :: ProposalBody
proposalBody = ProposalBody pVer protocolParamsUpdate sVer metaData

metaData :: M.Map SystemTag InstallerHash
metaData = M.singleton sysTag insHash

noPassSigningKey :: SafeSigner
noPassSigningKey = noPassSafeSigner sKey

protocolParamsUpdate :: ProtocolParametersUpdate
protocolParamsUpdate = createProtocolParametersUpdate
emptyProtocolParametersUpdate paramsToUpdate

createProtocolParametersUpdate
:: ProtocolParametersUpdate
-> [ParametersToUpdate]
-> ProtocolParametersUpdate
createProtocolParametersUpdate = go
where go i [] = i
go i (paramToUpdate : rest) =
case paramToUpdate of
ScriptVersion val -> go i{ppuScriptVersion = Just val} rest
SlotDuration val -> go i{ppuSlotDuration = Just val} rest
MaxBlockSize val -> go i{ppuMaxBlockSize = Just val} rest
MaxHeaderSize val -> go i{ppuMaxHeaderSize = Just val} rest
MaxTxSize val -> go i{ppuMaxTxSize = Just val} rest
MaxProposalSize val -> go i{ppuMaxProposalSize = Just val} rest
MpcThd val -> go i{ppuMpcThd = Just val} rest
HeavyDelThd val -> go i{ppuHeavyDelThd = Just val} rest
UpdateVoteThd val -> go i{ppuUpdateVoteThd = Just val} rest
UpdateProposalThd val -> go i{ppuUpdateProposalThd = Just val} rest
UpdateProposalTTL val -> go i{ppuUpdateProposalTTL = Just val} rest
SoftforkRuleParam val -> go i{ppuSoftforkRule = Just val} rest
TxFeePolicy val -> go i{ppuTxFeePolicy = Just val} rest
UnlockStakeEpoch val -> go i{ppuUnlockStakeEpoch = Just val} rest

emptyProtocolParametersUpdate :: ProtocolParametersUpdate
emptyProtocolParametersUpdate =
ProtocolParametersUpdate
{ ppuScriptVersion = Nothing
, ppuSlotDuration = Nothing
, ppuMaxBlockSize = Nothing
, ppuMaxHeaderSize = Nothing
, ppuMaxTxSize = Nothing
, ppuMaxProposalSize = Nothing
, ppuMpcThd = Nothing
, ppuHeavyDelThd = Nothing
, ppuUpdateVoteThd = Nothing
, ppuUpdateProposalThd = Nothing
, ppuUpdateProposalTTL = Nothing
, ppuSoftforkRule = Nothing
, ppuTxFeePolicy = Nothing
, ppuUnlockStakeEpoch = Nothing
}

data ParametersToUpdate =
ScriptVersion Word16
| SlotDuration Natural
| MaxBlockSize Natural
| MaxHeaderSize Natural
| MaxTxSize Natural
| MaxProposalSize Natural
| MpcThd LovelacePortion
| HeavyDelThd LovelacePortion
| UpdateVoteThd LovelacePortion
-- ^ UpdateVoteThd: This represents the minimum percentage of the total number of genesis
-- keys that have to endorse a protocol version to be able to become adopted.
| UpdateProposalThd LovelacePortion
-- ^ UpdateProposalTTL: If after the number of slots specified the proposal
-- does not reach majority of approvals, the proposal is simply discarded.
| UpdateProposalTTL SlotNumber
| SoftforkRuleParam SoftforkRule
| TxFeePolicy TxFeePolicy
| UnlockStakeEpoch EpochNumber
deriving Show

serialiseByronUpdateProposal :: ByronUpdateProposal () -> ByteString
serialiseByronUpdateProposal (ByronUpdateProposal proposal) = CBOR.serialize' proposal

deserialiseByronUpdateProposal :: ByteString -> Either CBOR.DecoderError (ByronUpdateProposal ByteString)
deserialiseByronUpdateProposal bs =
let lBs = LB.fromStrict bs
in case CBOR.decodeFull lBs of
Left deserFail -> Left deserFail
Right proposal -> Right . ByronUpdateProposal $ annotateProposal proposal lBs
where
annotateProposal :: AProposal CBOR.ByteSpan -> LB.ByteString -> AProposal ByteString
annotateProposal proposal bs' = CBOR.annotationBytes bs' proposal

updateProposalToGenTx :: ByronUpdateProposal ByteString -> Mempool.GenTx ByronBlock
updateProposalToGenTx (ByronUpdateProposal proposal) =
Mempool.ByronUpdateProposal (recoverUpId proposal) proposal

-- | Byron era votes

data ByronVote a = ByronVote { unByronVote :: AVote a}

createByronVote :: NetworkId -> SigningKey ByronKey -> ByronUpdateProposal ByteString -> Bool -> ByronVote ()
createByronVote nId (ByronSigningKey sKey) (ByronUpdateProposal proposal) yesOrNo =
ByronVote (mkVote (toByronProtocolMagicId nId) sKey (recoverUpId proposal) yesOrNo)

serialiseByronVote :: ByronVote () -> ByteString
serialiseByronVote (ByronVote vote) = CBOR.serialize' (void vote)

deserialiseByronVote :: ByteString -> Either CBOR.DecoderError (ByronVote ByteString)
deserialiseByronVote bs =
let lBs = LB.fromStrict bs
in case CBOR.decodeFull lBs of
Left deserFail -> Left deserFail
Right vote -> Right . ByronVote $ annotateVote vote lBs
where
annotateVote :: AVote CBOR.ByteSpan -> LB.ByteString -> AVote ByteString
annotateVote vote bs' = CBOR.annotationBytes bs' vote

voteToGenTx :: ByronVote ByteString -> Mempool.GenTx ByronBlock
voteToGenTx (ByronVote vote) = Mempool.ByronUpdateVote (recoverVoteId vote) vote


2 changes: 1 addition & 1 deletion cardano-cli/src/Cardano/CLI/Byron/Commands.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import Cardano.Chain.Update (InstallerHash (..), ProtocolVersion (..),
SoftwareVersion (..), SystemTag (..))

import Cardano.Api (NetworkId)
import Cardano.Api.Byron (ParametersToUpdate (..))

import Cardano.CLI.Byron.UpdateProposal

import Cardano.CLI.Byron.Genesis
import Cardano.CLI.Byron.Key
Expand Down
2 changes: 1 addition & 1 deletion cardano-cli/src/Cardano/CLI/Byron/Parsers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ import Cardano.Chain.Update (ApplicationName (..), InstallerHash (..),
import Cardano.Chain.UTxO (TxId, TxIn (..), TxOut (..))

import Cardano.Api hiding (Address, Lovelace, TxId, TxIn, TxOut, UpdateProposal)
import Cardano.Api.Byron (ParametersToUpdate (..))

import Cardano.CLI.Byron.Commands
import Cardano.CLI.Byron.Genesis
import Cardano.CLI.Byron.Key
import Cardano.CLI.Byron.Tx
import Cardano.CLI.Byron.UpdateProposal
import Cardano.CLI.Run (ClientCommand (ByronCommand))
import Cardano.CLI.Shelley.Commands (ByronKeyFormat (..))
import Cardano.CLI.Types
Expand Down
28 changes: 24 additions & 4 deletions cardano-cli/src/Cardano/CLI/Byron/Run.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Cardano.CLI.Byron.Run
( ByronClientCmdError
, renderByronClientCmdError
Expand All @@ -6,8 +9,9 @@ module Cardano.CLI.Byron.Run

import Cardano.Prelude

import Control.Monad.Trans.Except.Extra (firstExceptT, hoistEither)
import Control.Monad.Trans.Except.Extra (firstExceptT, hoistEither, left)
import qualified Data.ByteString.Char8 as BS
import qualified Data.Text as Text
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Text.Lazy.IO as TL
import qualified Formatting as F
Expand All @@ -16,14 +20,19 @@ import qualified Cardano.Chain.Common as Common
import qualified Cardano.Chain.Delegation as Delegation
import qualified Cardano.Chain.Genesis as Genesis
import Cardano.Chain.Slotting (EpochNumber)
import Cardano.Chain.Slotting (EpochSlots (..))
import Cardano.Chain.UTxO (TxIn, TxOut)

import qualified Cardano.Crypto.Hashing as Crypto
import qualified Cardano.Crypto.Signing as Crypto

import Cardano.Api hiding (TxIn, TxOut, UpdateProposal)
import Cardano.Api.Byron hiding (TxIn, TxOut, UpdateProposal)
import Cardano.Api.Protocol
import Cardano.Api.TxSubmit

import Ouroboros.Consensus.Byron.Ledger (ByronBlock)
import Ouroboros.Consensus.Ledger.SupportsMempool (ApplyTxErr)

import Cardano.CLI.Byron.Commands
import Cardano.CLI.Byron.Delegation
Expand All @@ -33,10 +42,11 @@ import Cardano.CLI.Byron.Query
import Cardano.CLI.Byron.Tx
import Cardano.CLI.Byron.UpdateProposal
import Cardano.CLI.Byron.Vote

import Cardano.CLI.Environment
import Cardano.CLI.Helpers
import Cardano.CLI.Shelley.Commands (ByronKeyFormat (..))
import Cardano.CLI.Types

-- | Data type that encompasses all the possible errors of the
-- Byron client.
data ByronClientCmdError
Expand All @@ -46,6 +56,7 @@ data ByronClientCmdError
| ByronCmdKeyFailure !ByronKeyFailure
| ByronCmdQueryError !ByronQueryError
| ByronCmdTxError !ByronTxError
| ByronCmdTxSubmitError !(ApplyTxErr ByronBlock)
| ByronCmdUpdateProposalError !ByronUpdateProposalError
| ByronCmdVoteError !ByronVoteError
deriving Show
Expand All @@ -59,6 +70,8 @@ renderByronClientCmdError err =
ByronCmdKeyFailure e -> renderByronKeyFailure e
ByronCmdQueryError e -> renderByronQueryError e
ByronCmdTxError e -> renderByronTxError e
ByronCmdTxSubmitError e ->
"Error while submitting Byron tx: " <> Text.pack (show e)
ByronCmdUpdateProposalError e -> renderByronUpdateProposalError e
ByronCmdVoteError e -> renderByronVoteError e

Expand Down Expand Up @@ -203,8 +216,15 @@ runCheckDelegation nw cert issuerVF delegateVF = do
runSubmitTx :: NetworkId -> TxFile -> ExceptT ByronClientCmdError IO ()
runSubmitTx network fp = do
tx <- firstExceptT ByronCmdTxError $ readByronTx fp
firstExceptT ByronCmdTxError $
nodeSubmitTx network (normalByronTxToGenTx tx)
SocketPath sockPath <- firstExceptT (ByronCmdTxError . EnvSocketError) readEnvSocketPath
withlocalNodeConnectInfo (ByronProtocol $ EpochSlots 21600) network sockPath $ \connectInfo ->
case localNodeConsensusMode connectInfo of
ByronMode{} -> do
result <- liftIO . submitTx connectInfo . TxForByronMode $ ByronTx tx
case result of
TxSubmitSuccess -> return ()
TxSubmitFailureByronMode err -> left $ ByronCmdTxSubmitError err
_ -> panic "Should be impossible"

runGetTxId :: TxFile -> ExceptT ByronClientCmdError IO ()
runGetTxId fp = firstExceptT ByronCmdTxError $ do
Expand Down
1 change: 0 additions & 1 deletion cardano-cli/src/Cardano/CLI/Byron/Tx.hs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ txSpendUTxOByronPBFT nw sk ins outs =

txattrs = Common.mkAttributes ()


-- | Submit a transaction to a node specified by topology info.
nodeSubmitTx
:: NetworkId
Expand Down
Loading

0 comments on commit 7a1a798

Please sign in to comment.