Skip to content

Commit dd7c020

Browse files
committed
Added CDDL prelude, fixed parser bugs
1 parent 3249265 commit dd7c020

File tree

9 files changed

+483
-70
lines changed

9 files changed

+483
-70
lines changed

bin/Main.hs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Main (main) where
44

55
import Codec.CBOR.Cuddle.CBOR.Gen (generateCBORTerm)
66
import Codec.CBOR.Cuddle.CDDL (Name (..), sortCDDL)
7+
import Codec.CBOR.Cuddle.CDDL.Prelude (prependPrelude)
78
import Codec.CBOR.Cuddle.CDDL.Resolve (
89
fullResolveCDDL,
910
)
@@ -25,9 +26,11 @@ import Text.Megaparsec (ParseErrorBundle, Parsec, errorBundlePretty, runParser)
2526

2627
data Opts = Opts Command String
2728

29+
newtype ValidateOpts = ValidateOpts {noPrelude :: Bool}
30+
2831
data Command
2932
= Format FormatOpts
30-
| Validate
33+
| Validate ValidateOpts
3134
| GenerateCBOR GenOpts
3235

3336
-- | Various formats for outputtting CBOR
@@ -78,6 +81,14 @@ pFormatOpts =
7881
<> help "Sort the CDDL rule definitions before printing."
7982
)
8083

84+
pValidateOpts :: Parser ValidateOpts
85+
pValidateOpts =
86+
ValidateOpts
87+
<$> switch
88+
( long "no-prelude"
89+
<> help "Do not include the CDDL prelude."
90+
)
91+
8192
opts :: Parser Opts
8293
opts =
8394
Opts
@@ -91,7 +102,7 @@ opts =
91102
<> command
92103
"validate"
93104
( info
94-
(pure Validate)
105+
(Validate <$> pValidateOpts)
95106
(progDesc "Validate the provided CDDL file")
96107
)
97108
<> command
@@ -125,9 +136,15 @@ run (Opts cmd cddlFile) = do
125136
Format fOpts ->
126137
let defs = if sort fOpts then sortCDDL res else res
127138
in putDocW 80 $ pretty defs
128-
Validate -> case fullResolveCDDL res of
129-
Left err -> putStrLnErr (show err) >> exitFailure
130-
Right _ -> exitSuccess
139+
Validate vOpts ->
140+
let
141+
resWithPrelude
142+
| noPrelude vOpts = res
143+
| otherwise = prependPrelude res
144+
in
145+
case fullResolveCDDL resWithPrelude of
146+
Left err -> putStrLnErr (show err) >> exitFailure
147+
Right _ -> exitSuccess
131148
(GenerateCBOR x) -> case fullResolveCDDL res of
132149
Left err -> putStrLnErr (show err) >> exitFailure
133150
Right mt -> do

cuddle.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ library
4747
Codec.CBOR.Cuddle.CDDL
4848
Codec.CBOR.Cuddle.CDDL.CtlOp
4949
Codec.CBOR.Cuddle.CDDL.CTree
50+
Codec.CBOR.Cuddle.CDDL.Prelude
5051
Codec.CBOR.Cuddle.CDDL.Postlude
5152
Codec.CBOR.Cuddle.CDDL.Resolve
5253
Codec.CBOR.Cuddle.Huddle
@@ -76,6 +77,7 @@ library
7677
, parser-combinators
7778
, prettyprinter
7879
, random <1.3
80+
, scientific
7981
, text
8082

8183
hs-source-dirs: src
@@ -120,6 +122,7 @@ test-suite cuddle-test
120122
other-modules:
121123
Test.Codec.CBOR.Cuddle.CDDL.Gen
122124
Test.Codec.CBOR.Cuddle.CDDL.Parser
125+
Test.Codec.CBOR.Cuddle.CDDL.Examples
123126
Test.Codec.CBOR.Cuddle.Huddle
124127

125128
-- other-extensions:

example/cddl-files/byron.cddl

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
; Cardano Byron blockchain CBOR schema
2+
3+
block = [0, ebblock]
4+
/ [1, mainblock]
5+
6+
mainblock = [ "header" : blockhead
7+
, "body" : blockbody
8+
, "extra" : [attributes]
9+
]
10+
11+
ebblock = [ "header" : ebbhead
12+
, "body" : [+ stakeholderid]
13+
, extra : [attributes]
14+
]
15+
16+
u8 = uint .lt 256
17+
u16 = uint .lt 65536
18+
u32 = uint
19+
u64 = uint
20+
21+
; Basic Cardano Types
22+
23+
blake2b-256 = bytes .size 32
24+
25+
txid = blake2b-256
26+
blockid = blake2b-256
27+
updid = blake2b-256
28+
hash = blake2b-256
29+
30+
blake2b-224 = bytes .size 28
31+
32+
addressid = blake2b-224
33+
stakeholderid = blake2b-224
34+
35+
epochid = u64
36+
slotid = [ epoch: epochid, slot : u64 ]
37+
38+
pubkey = bytes
39+
signature = bytes
40+
41+
; Attributes - at the moment we do not bother deserialising these, since they
42+
; don't contain anything
43+
44+
attributes = {* any => any}
45+
46+
; Addresses
47+
48+
addrdistr = [1] / [0, stakeholderid]
49+
50+
addrtype = &("PubKey" : 0, "Script" : 1, "Redeem" : 2) / (u64 .gt 2)
51+
addrattr = { ? 0 : addrdistr
52+
, ? 1 : bytes}
53+
address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
54+
55+
; Transactions
56+
57+
txin = [0, #6.24(bytes .cbor ([txid, u32]))] / [u8 .ne 0, encoded-cbor]
58+
txout = [address, u64]
59+
60+
tx = [[+ txin], [+ txout], attributes]
61+
62+
txproof = [u32, hash, hash]
63+
64+
twit = [0, #6.24(bytes .cbor ([pubkey, signature]))]
65+
/ [1, #6.24(bytes .cbor ([[u16, bytes], [u16, bytes]]))]
66+
/ [2, #6.24(bytes .cbor ([pubkey, signature]))]
67+
/ [u8 .gt 2, encoded-cbor]
68+
69+
; Shared Seed Computation
70+
71+
vsspubkey = bytes ; This is encoded using the 'Binary' instance
72+
; for Scrape.PublicKey
73+
vsssec = bytes ; This is encoded using the 'Binary' instance
74+
; for Scrape.Secret.
75+
vssenc = [bytes] ; This is encoded using the 'Binary' instance
76+
; for Scrape.EncryptedSi.
77+
; TODO work out why this seems to be in a length 1 array
78+
vssdec = bytes ; This is encoded using the 'Binary' instance
79+
; for Scrape.DecryptedShare
80+
vssproof = [bytes, bytes, bytes, [* bytes]] ; This is encoded using the
81+
; 'Binary' instance for Scrape.Proof
82+
83+
ssccomm = [pubkey, [{vsspubkey => vssenc},vssproof], signature]
84+
ssccomms = #6.258([* ssccomm])
85+
86+
sscopens = {stakeholderid => vsssec}
87+
88+
sscshares = {addressid => [addressid, [* vssdec]]}
89+
90+
ssccert = [vsspubkey, pubkey, epochid, signature]
91+
ssccerts = #6.258([* ssccert])
92+
93+
ssc = [0, ssccomms, ssccerts]
94+
/ [1, sscopens, ssccerts]
95+
/ [2, sscshares, ssccerts]
96+
/ [3, ssccerts]
97+
98+
sscproof = [0, hash, hash]
99+
/ [1, hash, hash]
100+
/ [2, hash, hash]
101+
/ [3, hash]
102+
103+
; Delegation
104+
105+
dlg = [ epoch : epochid
106+
, issuer : pubkey
107+
, delegate : pubkey
108+
, certificate : signature
109+
]
110+
111+
dlgsig = [dlg, signature]
112+
113+
lwdlg = [ epochRange : [epochid, epochid]
114+
, issuer : pubkey
115+
, delegate : pubkey
116+
, certificate : signature
117+
]
118+
119+
lwdlgsig = [lwdlg, signature]
120+
121+
; Updates
122+
123+
bver = [u16, u16, u8]
124+
125+
txfeepol = [0, #6.24(bytes .cbor ([bigint, bigint]))]
126+
/ [u8 .gt 0, encoded-cbor]
127+
128+
bvermod = [ scriptVersion : [? u16]
129+
, slotDuration : [? bigint]
130+
, maxBlockSize : [? bigint]
131+
, maxHeaderSize : [? bigint]
132+
, maxTxSize : [? bigint]
133+
, maxProposalSize : [? bigint]
134+
, mpcThd : [? u64]
135+
, heavyDelThd : [? u64]
136+
, updateVoteThd : [? u64]
137+
, updateProposalThd : [? u64]
138+
, updateImplicit : [? u64]
139+
, softForkRule : [? [u64, u64, u64]]
140+
, txFeePolicy : [? txfeepol]
141+
, unlockStakeEpoch : [? epochid]
142+
]
143+
144+
updata = [ hash, hash, hash, hash ]
145+
146+
upprop = [ "blockVersion" : bver
147+
, "blockVersionMod" : bvermod
148+
, "softwareVersion" : [ text, u32 ]
149+
, "data" : #6.258([text, updata])
150+
, "attributes" : attributes
151+
, "from" : pubkey
152+
, "signature" : signature
153+
]
154+
155+
upvote = [ "voter" : pubkey
156+
, "proposalId" : updid
157+
, "vote" : bool
158+
, "signature" : signature
159+
]
160+
161+
up = [ "proposal" : [? upprop]
162+
, votes : [* upvote]
163+
]
164+
165+
; Blocks
166+
167+
difficulty = [u64]
168+
169+
blocksig = [0, signature]
170+
/ [1, lwdlgsig]
171+
/ [2, dlgsig]
172+
173+
blockcons = [slotid, pubkey, difficulty, blocksig]
174+
175+
blockheadex = [ "blockVersion" : bver
176+
, "softwareVersion" : [ text, u32 ]
177+
, "attributes" : attributes
178+
, "extraProof" : hash
179+
]
180+
181+
blockproof = [ "txProof" : txproof
182+
, "sscProof" : sscproof
183+
, "dlgProof" : hash
184+
, "updProof" : hash
185+
]
186+
187+
blockhead = [ "protocolMagic" : u32
188+
, "prevBlock" : blockid
189+
, "bodyProof" : blockproof
190+
, "consensusData" : blockcons
191+
, "extraData" : blockheadex
192+
]
193+
194+
blockbody = [ "txPayload" : [* [tx, [* twit]]]
195+
, "sscPayload" : ssc
196+
, "dlgPayload" : [* dlg]
197+
, "updPayload" : up
198+
]
199+
200+
; Epoch Boundary Blocks
201+
202+
ebbcons = [ epochid, difficulty ]
203+
204+
ebbhead = [ "protocolMagic" : u32
205+
, "prevBlock" : blockid
206+
, "bodyProof" : hash
207+
, "consensusData" : ebbcons
208+
, "extraData" : [attributes]
209+
]

example/cddl-files/conway.cddl

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,83 @@
1+
; crypto.cddl
2+
$hash28 /= bytes .size 28
3+
$hash32 /= bytes .size 32
4+
5+
$vkey /= bytes .size 32
6+
7+
$vrf_vkey /= bytes .size 32
8+
$vrf_cert /= [bytes, bytes .size 80]
9+
10+
$kes_vkey /= bytes .size 32
11+
$kes_signature /= bytes .size 448
12+
signkeyKES = bytes .size 64
13+
14+
$signature /= bytes .size 64
15+
16+
; extra.cddl
17+
; Conway era introduces an optional 258 tag for sets, which will become mandatory in the
18+
; second era after Conway. We recommend all the tooling to account for this future breaking
19+
; change sooner rather than later, in order to provide a smooth transition for their users.
20+
21+
; This is an unordered set. Duplicate elements are not allowed and the order of elements is implementation specific.
22+
set<a> = #6.258([* a]) / [* a]
23+
24+
; Just like `set`, but must contain at least one element.
25+
nonempty_set<a> = #6.258([+ a]) / [+ a]
26+
27+
; This is a non-empty ordered set. Duplicate elements are not allowed and the order of elements will be preserved.
28+
nonempty_oset<a> = #6.258([+ a]) / [+ a]
29+
30+
positive_int = 1 .. 18446744073709551615
31+
32+
unit_interval = #6.30([1, 2])
33+
; unit_interval = #6.30([uint, uint])
34+
;
35+
; Comment above depicts the actual definition for `unit_interval`.
36+
;
37+
; Unit interval is a number in the range between 0 and 1, which
38+
; means there are two extra constraints:
39+
; * numerator <= denominator
40+
; * denominator > 0
41+
;
42+
; Relation between numerator and denominator cannot be expressed in CDDL, which
43+
; poses a problem for testing. We need to be able to generate random valid data
44+
; for testing implementation of our encoders/decoders. Which means we cannot use
45+
; the actual definition here and we hard code the value to 1/2
46+
47+
48+
nonnegative_interval = #6.30([uint, positive_int])
49+
50+
51+
address =
52+
h'001000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000' /
53+
h'102000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000' /
54+
h'203000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000' /
55+
h'304000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000' /
56+
h'405000000000000000000000000000000000000000000000000000000087680203' /
57+
h'506000000000000000000000000000000000000000000000000000000087680203' /
58+
h'6070000000000000000000000000000000000000000000000000000000' /
59+
h'7080000000000000000000000000000000000000000000000000000000'
60+
61+
reward_account =
62+
h'E090000000000000000000000000000000000000000000000000000000' /
63+
h'F0A0000000000000000000000000000000000000000000000000000000'
64+
65+
bounded_bytes = bytes .size (0..64)
66+
; the real bounded_bytes does not have this limit. it instead has a different
67+
; limit which cannot be expressed in CDDL.
68+
; The limit is as follows:
69+
; - bytes with a definite-length encoding are limited to size 0..64
70+
; - for bytes with an indefinite-length CBOR encoding, each chunk is
71+
; limited to size 0..64
72+
; ( reminder: in CBOR, the indefinite-length encoding of bytestrings
73+
; consists of a token #2.31 followed by a sequence of definite-length
74+
; encoded bytestrings and a stop code )
75+
76+
; a type for distinct values.
77+
; The type parameter must support .size, for example: bytes or uint
78+
distinct<a> = a .size 8 / a .size 16 / a .size 20 / a .size 24 / a .size 30 / a .size 32
79+
80+
; conway.cddl
181
block =
282
[ header
383
, transaction_bodies : [* transaction_body]
@@ -87,9 +167,9 @@ proposal_procedure =
87167
, anchor
88168
]
89169

90-
proposal_procedures = nonempty_oset<proposal_procedure>
170+
proposal_procedures = nonempty_set<proposal_procedure>
91171

92-
certificates = nonempty_oset<certificate>
172+
certificates = nonempty_set<certificate>
93173

94174
gov_action =
95175
[ parameter_change_action

0 commit comments

Comments
 (0)